Search code examples
htmlcssiframejekyll

How can I embed prestyled HTML with being effected by the surrounding CSS?


I'm trying to embed a preformatted scientific paper into my website, without interference from my website's theme. The article is comprised of HTML and CSS content generated from a LaTeX manuscript, which I want to render exactly as-is. My website's theme ends up styling parts of that article's HTML content, which I'm trying to avoid. For example, the theme's stylesheet has rules for link formatting that are more specific than those specified by the article.scss, so they take precedence.

This is just a simple GitHub Pages site that's statically generated by Jekyll, but this question is more general than that. I'm using a a third party theme that styles just about everything and works really well on most pages, where I just provide dumb MarkDown content for it to style and present.

On this article's page, I want to use the common site header (so I need the theme.scss, I can't just skip it for that page), but the rest of the page content should just be the article's HTML as-is, with its own article.scss for styling it.

What's the best way to embed this article's HTML and CSS on a "clean slate"?

One approach to fix this was to find all the offending theme rules, and add new more-specific rules like .article p { font-size: unset; }, etc. This was annoying but worked decently well on my first go at this, but unfortunately, it totally breaks when I change the theme: some of those "reset rules" become obsolete, and other new ones need to be made for the new theme's quirks.

An iframe came to mind, but that gave me a "you're doing it wrong" feeling. Is there a native CSS way to say something like "this tag and its children belong to their new isolated context, with their own set of styles"?


Solution

  • I believe the most appropriate approach is to use the Shadow DOM, which can be done from pure HTML like so:

    p { color: red; }
    <p>Text red</p>
    
    <div>
      <template shadowrootmode="open">
        <style>p {text-decoration: underline}</style>
        <p>Text in shadow DOM and not affected by red</p>
      </template>
    </div>

    Alternatively, you can also use JS to dynamically load content in your Shadow DOM.

    I hope that can help you.