1

In my css/scss file I have the below page style, how can I reference it from my react component that wraps everything on the page? Or rather what is a way to pass to my page?

@page {
    size: 5in 6in;
    margin: 1in 1in 1.25in 1in;
}

Page component :

    <MyThemeProvider theme={frog}>
        <main className="page-container">
              ..... children .....

        </main>
    </MyThemeProvider>

I expect that the CSS rule should be effective when I print this page to PDF.

mcvkr
  • 3,209
  • 6
  • 38
  • 63

3 Answers3

0

Or rather what is a way to pass to my page?

I think this is a simpler way to look at it, yes. A react app is a web page (html) that loads a bunch of javascript.

From a web page perspective, CSS is observed by the web browser, so if the rule is defined, it will apply to qualifying elements regardless of if the DOM is static or if there is a react app manipulating it.

For an at-rule such as @page, having it defined it in a style element in the index.html would do the trick without managing it in your React component at all.

Example in the average create-react-app index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta name="theme-color" content="#000000">
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json">
    <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
    <title>React App</title>
    <style>
        @page {
            size: 5in 6in;
            margin: 1in 1in 1.25in 1in;
        }
    </style>
  </head>
  <body>
    <noscript>
      You need to enable JavaScript to run this app.
    </noscript>
    <div id="root"></div>
  </body>
</html>

Tacking your comment into account, that style can be define pretty much anywhere in the body of the page, and therefore you can define it in any one of your react components.

See here for a similar use-case : https://stackoverflow.com/a/66627107/18706075

M. Gallant
  • 236
  • 2
  • 5
  • I updated the question, I dont have an index.html in my project. They are all react/typescript files. – mcvkr Aug 04 '22 at 18:10
  • I understand by this that your index.html is generated from scratch when you "build" your project, and that you are not in a position to have it generated with the additional style as suggested. I'll update my answer with this in mind, but please comment if this is not accurate. – M. Gallant Aug 04 '22 at 20:54
  • It is accurate and for that reason now I am trying something like this https://gist.github.com/yamadayuki/f1ea9ccacad7f1c140457b5877fb54cc – mcvkr Aug 04 '22 at 21:40
  • 1
    The impact would not be dramatic unless you accumulate thousands of them, but the approach you linked to will require more careful implementation Vs the in-component or a static definition as it appends a new style element each time it is called. The in-component approach is self-cleaning so-to-speak. Obviously, the index.html would have been set and forget. If you favor that approach, I recommend you add an id to your appended style element and check wether that element exists before appending a new instance. – M. Gallant Aug 04 '22 at 22:12
0

Actually, no need for hacks out of React.

Please see below, for the custom ContentContainer component code:

import React from 'react';
// other imports

const GlobalStyler = () => (
    <style>{`
        @page {
            size: 5in 6in;
            margin: 1in 1in 1.25in 1in;
        }
  `}</style>
);

const ContentContainer = (props: ContentContainerProps) => {
    return (
        <div>
            <GlobalStyler />
            // other content/components 
        </div>
    );
};

export default ContentContainer;

Here is how your style will end up

enter image description here

mcvkr
  • 3,209
  • 6
  • 38
  • 63
0

You can do:

import React from 'react';
import './global.css';

const ContentContainer = ({theme, ...props}) => (
    <div className={theme} ...props>
          ..... children .....
    </div>
);

export default ContentContainer;

and global.css:

div.frog, div.frog * {
    size: 5in 6in;
    margin: 1in 1in 1.25in 1in;
}

and use it like:

import { ContentContainer } from 'contentContainer.jsx';

myMain = () => (
    <ContentContainer theme="frog" />
);