how to import css file in react when generating static html and inject imported css into html head tag? - reactjs

I am trying to generate static html from react using renderToStaticMarkup method. The problem I am facing right now is that I am not able to import css into react component. I want to import css in my React components like css-modules (import styles from './style.css'). And then inject that loaded css into generated static html head. How can I accomplish that?
P.S. I can't use webpack due to some constraints. If there is any babel plugin availabe for this specific case, then please let me know.
Here is how I am generating static html from react component:
const reactElement = require('react').createElement;
const ReactDomServer = require('react-dom/server');
const renderHTML = Component => {
return ReactDomServer.renderToString(reactElement(Component))
}

You can pass a URL in as a prop and render a <link/> tag. Made an example here, not sure if that would meet your needs or if you need it to be a style tag.

This may be challenging without a lot of custom logic.
If you want to inline the CSS only for the initial render and then fetch the rest after the initial render, styled-components may be a better option because it supports exactly what you're trying to achieve without too much configuration: https://www.styled-components.com/docs/advanced#server-side-rendering

May be I am too late you can also create It like this way.
React.createElement("style", {},[ "body {background-color: powderblue;}
h1 {color: blue;}
p {color: red;}" ])
Output:
<style>
body {background-color: powderblue;}
h1 {color: blue;}
p {color: red;}
</style>
Since createElement take 3 params and last one is children we can put our vanila css inside it as a children. You can put any imported file in the form of string and it will convert to style tag

Related

Create Html from React Component including Style

I have a simple react component in which using ref I am getting the div but I have to generate a html includes styling as well. So I can pass this html to PDF generation backend server.
pdfRef(elem){
console.log(elem);
//<div><span>dataPDF</span> </div>
}
render() {
return (
<div ref={(elem) => this.pdfRef(elem)} className="SomeCssClass">
<span >dataPDF</span>
</div>
);
}
}
[Edit]
When I try to print the div via ref, the elements are printed with class name. But when I send this string to pdf service, since only html element is sent and class name without the actual css , the pdf is generated without style.
is there any way to generate html with css as as string so further it can be send to pdf service. Hope the question is clear
Any pointers?
The server.js script in react-dom lets you render a React component to static html string. You can require it in your code like:
const ReactDOMServer = require('react-dom/server');
Or using ES6 syntax:
import ReactDomServer from 'react-dom/server'
After this you can render your component to HTML string using the ReactDomServer.renderToString or ReactDomServer.renderToStaticMarkup functions as follows:
const htmlStr = ReactDomServer.renderToStaticMarkup(<MyComponent prop1={'value1'} />);
This looks almost exactly like ReactDom.render, except that it doesn't need the second parameter of dom node to render at, and the html string is returned. Additionally this method can be used on both client and server side. For your generate-pdf use case renderToStaticMarkup would suffice. If required check the documentation at following link for subtle difference between the two methods mentioned above: https://reactjs.org/docs/react-dom-server.html

Loading Sass and injecting CSS text into a parent document from a React app

I have a React app that's loaded into a parent document via some shim JavaScript that:
creates an <iframe> element
creates a <div>
injects a <style> tag into the <head> in order to style the inserted <div>
Roughly, this works using the below:
// example.jsx
// Require the css using css-loader
const styles = require('../styles/example.css');
// Find the parent document
const doc = window.parent.document;
// Inject our stylesheet for the widget into the parent document's
// HEAD as a style tag
const css = styles.toString();
const style = doc.createElement('style');
style.type = 'text/css';
if (style.styleSheet) {
// This is required for IE8 and below.
style.styleSheet.cssText = css;
} else {
style.appendChild(document.createTextNode(css));
}
doc.head.appendChild(style);
This uses css-loader in our Webpack config in order to have the require().toString() work for setting the cssText dynamically.
While this works, I don't know if this ideal. And we'd prefer to write Sass and get the benefits of #import to bring in other CSS (like resets), and get the benefits other tooling for Sass.
Is there a better way that we can achieve the same result of injecting <style> text into this parent document without sacrificing our ability to use the tooling we prefer?
Install react-helmet and then try this in your react component:
<Helmet>
<style>
// Insert CSS string here
</style>
</Helmet>
The other option is to load the sass directly in the parent but gate all of its styling behind a sass function that checks if #react-root exists.

what does this syntax in styled-components actually mean?

I've just started using styled-components and saw that they call what i presume is a function like so:
import styled from "styled-components"
const Button = sytled.button` <--- this
// css goes here
`
I've never seem that syntax before and wanted to know if someone could point me to some docs about what it actually is.
It's called tagged template literals. The "tag" is the function before the template literal, which is called with its parameters being the template and template's variables. The parameters are as follow:
An array with all the string parts between the ${variables}.
First ${variable} of the template.
Second ${variable} of the template.
etc...
For example, I have written a function named tag that does the same as the function template literals use to process when you don't specify any tag function (a.k.a its default function):
function tag(stringParts, ...values){
return stringParts.reduce((accum, part, index) => accum + values[index-1] + part);
}
Calling it this way
tag`Hello, ${name}! I found ${count} results.`
yields the same result as
`Hello, ${name}! I found ${count} results.`
and the params fed to the tag function are ['Hello, ', '! I found ', ' results.'], name and count.
That's how you set the CSS rules for the <button> element.
So then you can use it as such:
<Button>Hello world</Button>
and all the styles you wrote above would get applied to all <Button> elements
Styled-components is a library used for styling react components.
import styled from "styled-components"
const Button = sytled.button` <--- this
// css goes here
`;
`` <-- these are template literals which was introduced in ES6.
styled is an object here and when you say styled.button it means that we are styling html tags. So you can style a div, container, h1 etc. You want to use standard css to style these html tags and styled-components create a random classname for the same.
let's say you want to style a div. You name it a Wrapper. The naming covention is first letter always capital.
const Wrapper = styled.div`
background: #c0c0aa; /* fallback for old browsers */
background: -webkit-linear-gradient(to right, #1cefff, #c0c0aa); /* Chrome 10-25, Safari 5.1-6 */
background: linear-gradient(to right, #1cefff, #c0c0aa); /* W3C, IE 10+/ Edge, Firefox 16+, Chrome 26+, Opera 12+, Safari 7+ */
height: 100%;
width: 100%;
`;
now you can wrap your content in render () of react.
<Wrapper>
//Your code in render of react class goes here
//thus instead of <div className = 'Wrapper'>
//you use the above code
//styled-components automatically generates random classnames solving major problems
</ Wrapper>
for more information see Max Stoiber's keynote at React Amsterdam.
https://www.styled-components.com/docs/basics#motivation

how to use common less variable with styled component?

Say I have a styled component, in index.jsx
import './index.less';
class Input extends React.Component {
...
}
and my index.less files looks:
.input{
color: #whiteColor;
}
This index.less has to work with the mixin.less that imported in the root project.
So my question is, even though I imported the mixin.less, it prompts variable #whiteColor not found. Any idea to solve this?
I have felt the same pain, why isn't my styled component resolving less variables?
The syntax is simple JavaScript, just do:
.input{
color: ${props => props.whiteColor};
// or
color: ${props => props.theme.whiteColor};
}
But, at my company, we had thousands of less components, and we really thought that the less syntax was cleaner and definitely faster to write. We developed Styless.
It is a babel plugin that parses less and generates javascript code. Add it to your .babelrc file.
{
"plugins": ["babel-plugin-styless"]
}
Then, we can do!!
const Input = styled.input`
#highlight: blue; // can be overwritten by theme or props
background: darken(#highlight, 5%); // make green darken by 5%
`;
Check here to see how to use the theme provider and load variable from your index.less!
You can try import the mixin.less in index.less
I have been trying the same than you.
But then I thought.. it is that what I really want? Because styled-components propose a different approach to having a modular structure for your styles.
https://www.styled-components.com/docs/advanced Check theming, is amazing powerful.
Because in styled components you define the variables with javascript.
And if you want color manipulation like less, sass, you can check https://github.com/erikras/styled-components-theme
Its like forgetting about less, and sass and moving it to a new style modules.
Still, if you want to keep your defined style classes, you can do that:
class MyComponent extends React.Component {
render() {
// Attach the passed-in className to the DOM node
return <div className={`some-global-class ${this.props.className}`} />;
}
}
Check the existing CSS usage from docs:
https://www.styled-components.com/docs/advanced#existing-css

Rollup and Post CSS - Auto-prefixing React className attributes

I'm using Rollup + React + Post CSS to build a component library. I'm looking for a way to autoprefix class names so that they will not conflict with styles in the project using the library.
I have already added this plugin to automate adding the 'prefix-' to every class name in the CSS:
Post CSS Prefixer
However, this does not modify the JavaScript (JSX), so the React components are still using the unnamed classes as className attributes.
Is there a way to use Rollup to automatically modify className attributes to include the same prefix specified in the CSS?
Note that I'm not looking for a fully modular solution such as CSS Modules, as I want the same 'prefix-' across every component inside the library.
You can't use static classNames to use this feature. To use it you need import style as object and assign it as object also.
import React from "react";
import style from "style.css";
class DivMyStyle extends React.Component {
render() {
return <div className={style.myStyle} />
}
}

Resources