Question

Apply CSS to an iframe: Same-Origin Styling in HTML

csshtmliframerss

Question

I have a simple HTML page containing several <iframe> elements that display RSS-related pages. How can I apply the same CSS styles from the main page to the document displayed inside each iframe?

Short Answer

An iframe contains a separate HTML document, so CSS rules from the parent page do not automatically cross into it. You will learn how to style iframe content when both pages are under your control and on the same origin, plus what to do when embedded content comes from another website.

Concept

An <iframe> is not just a visual section of a page. It loads a complete, separate document with its own:

  • HTML structure
  • CSS stylesheets
  • JavaScript environment
  • window and document objects

Therefore, this CSS in a parent page affects the iframe element itself, but not the page loaded inside it:

iframe {
  width: 100%;
  border: 0;
}

To style the iframe's internal document, that document must load its own CSS. If you own both documents and they have the same origin, JavaScript can also access the iframe document and add a stylesheet dynamically.

An origin is generally the combination of protocol, host, and port. For example:

  • https://example.com/page.html and https://example.com/feed.html are usually same-origin.
  • https://example.com and https://feeds.example.net are cross-origin.
  • http://example.com and https://example.com are cross-origin because the protocol differs.

Browser security rules prevent a page from reading or changing cross-origin iframe content. This protects users from a malicious site embedding a bank or email site and trying to inspect private information.

Mental Model

Think of an iframe as a separate apartment inside a building.

  • The parent page can paint the outside of the apartment door: the iframe's size, border, position, and background around it.
  • The parent page cannot rearrange furniture inside the apartment just because it is in the same building.
  • If you own both apartments and have the key (same origin), JavaScript can enter and make changes.
  • If another organization owns the apartment (cross-origin), the browser does not give you the key.

The most reliable approach is to put the shared styling rules in a CSS file that both documents load.

Take Quiz

Syntax and Examples

Style the iframe element from the parent document:

<!-- index.html -->
<iframe class="rss-frame" src="rss-view.html" title="RSS links"></iframe>
/* main.css */
.rss-frame {
  display: block;
  width: 100%;
  min-height: 240px;
  border: 1px solid #cbd5e1;
  border-radius: 8px;
}

This styles the frame's box, not the content in rss-view.html.

To give both pages the same visual styles, load one shared stylesheet in each document:

<!-- index.html -->
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <link rel="stylesheet" href="shared.css">
</head>
<body>
  <h1>News</h1>
  <iframe class="rss-frame" src="rss-view.html" title="RSS links"></iframe>
</body>
</html>
<!-- rss-view.html -->
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <link rel="stylesheet" href="shared.css">
</head>
<body>
  <ul class="feed-list">
    <li><a href="/articles/1">New release notes</a></li>
    <li><a href="/articles/2">Weekly engineering update</a></li>
  </ul>
</body>
</html>
/* shared.css */
body {
  margin: 0;
  font-family: system-ui, sans-serif;
  color: #1e293b;
}

.feed-list {
  padding: 1rem 1.5rem;
}

a {
  color: #2563eb;
}

The two documents remain separate, but they use identical CSS rules from the same file.

Step by Step Execution

Consider two files hosted at https://my-site.test:

<!-- parent.html -->
<iframe id="feed" src="feed.html" title="Feed"></iframe>

<script>
  const frame = document.querySelector('#feed');

  frame.addEventListener('load', () => {
    const frameDocument = frame.contentDocument;
    frameDocument.body.classList.add('embedded-feed');
  });
</script>
<!-- feed.html -->
<style>
  .embedded-feed {
    background: #f8fafc;
    font-family: Arial, sans-serif;
  }
</style>

<p>Latest RSS item</p>

Execution flow:

  1. The browser loads parent.html.
  2. It creates the iframe and requests feed.html.
  3. The iframe finishes loading and emits its load event.
  4. The callback reads frame.contentDocument, which represents feed.html's document.
  5. The script adds embedded-feed to the iframe document's <body>.
  6. The CSS declared in feed.html matches that class and changes the iframe content.

This works only when the parent and feed.html are same-origin. If src points to a different origin, accessing contentDocument may be unavailable or attempting to use its contents will be blocked by the browser.

Real World Use Cases

  • Documentation previews: An application embeds HTML previews that use the same design system stylesheet as the main interface.
  • Internal dashboards: A portal embeds reports generated by another route on the same company domain.
  • Legacy migrations: A modern shell page embeds an older page while both gradually adopt shared CSS.
  • Widget configuration: A site owns an iframe-based editor and applies a theme class after the editor loads.
  • RSS presentation: Rather than embedding a third-party feed page, a server fetches and parses permitted feed data, then renders it in the site's own HTML template.

For third-party embeds such as a social media post, payment form, map, or externally hosted RSS viewer, use the provider's documented appearance options. The provider may offer query parameters, a configuration API, or a theme setting, but your parent CSS cannot override arbitrary content inside its iframe.

Take Quiz

Real Codebase Usage

In real projects, developers usually avoid copying a large <style> block into every iframe page. Common patterns include:

  • Shared stylesheet: Both the parent and iframe document load shared.css or a design-system stylesheet.
  • Theme variables: Each document loads the same CSS variables, such as --brand-color and --surface-color.
  • Iframe-specific stylesheet: The embedded page loads embed.css in addition to shared styles to remove margins or adjust compact layouts.
  • Same-origin initialization: A parent listens for load before using iframe.contentDocument or iframe.contentWindow.
  • Cross-origin messaging: If both applications cooperate but are hosted on different origins, they use window.postMessage() to request supported theme changes. The iframe application must explicitly listen for and validate those messages.
  • Server-side rendering: For RSS data, the application often fetches the feed on the server or through a backend endpoint and renders the items directly, avoiding iframe styling and layout limitations.

A practical shared-theme setup might look like this:

<!-- In every document you control -->
<link rel="stylesheet" href="/assets/design-system.css">
<link rel="stylesheet" href="/assets/embed.css">

embed.css can be included only by iframe pages when they need embedded-specific adjustments.

Common Mistakes

Expecting parent selectors to enter the iframe

This does not style paragraphs inside the embedded page:

iframe p {
  color: red;
}

An iframe is replaced content, not a normal container whose descendants CSS can select. Use CSS within the iframe document instead.

Styling only the iframe box

iframe {
  background: black;
  color: white;
}

This may affect the space around or behind the embedded document, but color does not automatically change text inside the iframe. Add styles to the iframe page.

Trying to access a cross-origin iframe with JavaScript

const frame = document.querySelector('iframe');
frame.contentDocument.body.style.color = 'red';

This is blocked when the iframe loads a different origin. You cannot bypass this with CSS, JavaScript, or CORS headers on the parent page.

Running code before the iframe loads

The iframe document may not exist yet when the parent script first runs. Wait for load:

frame.addEventListener('load', () => {
  frame.contentDocument.body.classList.add('compact');
});

Assuming sandbox grants access

The sandbox attribute restricts iframe capabilities; it does not let a parent access cross-origin content. In fact, sandbox settings can make access more restrictive.

Embedding raw RSS XML

RSS feeds are often XML, not a styled HTML page designed for embedding. A better user experience is usually to parse the feed and render safe, formatted links in your own page.

Comparisons

ApproachCan style iframe content?Best use case
Parent CSS targeting iframeNo, only the frame boxSet dimensions, borders, and layout
Shared CSS loaded by both documentsYesYou control both same-origin documents
Parent JavaScript with contentDocumentYes, same-origin onlySmall dynamic adjustments after loading
postMessage()Only if the iframe implements itCooperative cross-origin applications
Provider theme/configuration optionsSometimesThird-party widgets and embeds
Render RSS data in the parent pageYesFull design control over feed content
TermMeaning
Same-originParent and iframe share compatible protocol, host, and port
Cross-originThe pages differ by protocol, host, or port
CORSA server mechanism for cross-origin network requests; it does not grant DOM access to iframe content
Take Quiz

Cheat Sheet

<!-- Style the iframe element -->
<iframe class="panel" src="embedded.html" title="Embedded content"></iframe>
.panel {
  width: 100%;
  height: 300px;
  border: 0;
}
<!-- Put this in BOTH documents for shared styles -->
<link rel="stylesheet" href="/css/shared.css">
// Same-origin only: wait until the iframe has loaded.
const frame = document.querySelector('iframe');
frame.addEventListener('load', () => {
  frame.contentDocument.body.classList.add('theme-dark');
});

Key rules:

  • Parent CSS cannot select elements inside an iframe.
  • An iframe page should normally load its own stylesheet.
  • JavaScript access to iframe DOM content requires same-origin pages.
  • CORS does not allow a parent to manipulate a cross-origin iframe's DOM.
  • For third-party iframes, use documented customization options or render the data yourself.

FAQ

Can CSS from the parent page style an iframe's contents?

No. The parent stylesheet can style the <iframe> element but not the separate document loaded inside it.

How do I use the same CSS in a parent page and iframe?

Place shared rules in a CSS file, such as shared.css, and include that file with a <link> element in both HTML documents.

Can JavaScript style an iframe after it loads?

Yes, if the iframe document is same-origin. Listen for the iframe's load event, then use contentDocument or contentWindow.document.

Why do I get a cross-origin error when accessing an iframe?

The parent and iframe have different origins, such as different domains, protocols, or ports. The browser blocks access for security.

Does enabling CORS let me style an external iframe?

No. CORS controls certain network requests; it does not permit DOM access to a cross-origin iframe.

Can I style an external RSS feed inside an iframe?

Not unless the external site provides styling controls or you control its page. Usually, fetch or process the feed through an authorized backend and render the feed items in your own HTML.

Why should every iframe have a title?

A descriptive title helps screen-reader users understand the purpose of the embedded content.

Take Quiz

Mini Project

Description

Create a small news dashboard that embeds a same-origin feed page. The parent page controls the frame layout, while the parent and feed page share a stylesheet so the interface has one consistent appearance.

Goal

Build a styled same-origin iframe whose internal content uses the same shared CSS as the main page.

Requirements

Create a parent page containing an iframe with a descriptive title. Create a separate HTML page to load inside the iframe. Use one shared CSS file in both documents. Style the iframe element independently for size and border. Display at least two feed links inside the embedded page.

Take Quiz

Keep learning

Related questions

View more