When importing standard css files from node modules, e.g.:
import 'reset-css/reset.css';
import 'semantic-ui-css/components/form.min.css';
import 'semantic-ui-css/components/message.min.css';
and when you're using styled components, only the styled components remain. The styles of the _normal css files_ imported from node modules disappear / are missing (in the AMP version).
Steps to reproduce the behavior, please provide code snippets or a repository:
import 'reset-css/reset.css';
)Import both styled components and other imported css from files.
Styled components seem to be working as of this version for AMP, but other css next to styled components is being thrown away in the AMP version.
Hi, you can use the styled-jsx Webpack loader to import external CSS in AMP mode for now. You just have to be careful to not go over the 50,000 bytes limit for styles in AMP.
@ijjk Could you illustrate with an example how that's supposed to work? Because this doesn't.
{isAmp && (
<style jsx global>{`
@import '~reset-css/reset.css';
@import '~semantic-ui-css/components/form.min.css';
@import '~semantic-ui-css/components/message.min.css';
body {
background: red;
}
`}</style>
)}
Edit: to clarify; background: red;
works, but the external stylesheets are not loaded.
@wouterds I was mistaken, we don't support that in AMP mode right now (sorry about that), currently to do this you would need to load the styles in a custom _document
. Note: this is not ideal and is just a workaround you can use while official handling of this is implemented.
Example with custom pages/_document
:
import Document, { Html, Head, Main, NextScript } from 'next/document'
import fs from 'fs'
import path from 'path'
import { promisify } from 'util'
const readFile = promisify(fs.readFile)
class MyDocument extends Document {
static async getInitialProps(ctx) {
const initialProps = await Document.getInitialProps(ctx)
// assumes .next is your distDir
const projectDir = __dirname.split('.next')[0]
const customStyles = await readFile(
// to load normalize from node_modules change
// styles.css to node_modules/normalize.css/normalize.css
path.join(projectDir, 'styles.css'),
'utf8'
)
return {
...initialProps,
styles: (
<>
<style dangerouslySetInnerHTML={{
__html: customStyles
}} />
{initialProps.styles}
</>
)
}
}
render() {
return (
<Html>
<Head />
<body>
<Main />
<NextScript />
</body>
</Html>
)
}
}
export default MyDocument
I don't want to bother anyone, but any progress on this, guys?
@ijjk how would you do it when you have app/pages
instead of <rootdir>/pages
?
@koenverburg it should work the same, are you getting an error using the above workaround?
@timneutkens any clue on an ETA to _actually_ support AMP within this project?
Will probably be part of https://github.com/zeit/next.js/issues/8626
Haven't prioritized this issue in particular, there are more important ones on the roadmap.
It's unfair to say "actually support", Next.js supports AMP out of the box, you're adding in non-standard behavior (css imports) and linking css files is not even supported in AMP, they'd have to be inlined also.
So you know how when you run a import './my-styles.css'
- why does next link that on browser runtimes, but gets completely ignored for amp builds? Why cant next just inline that import, much like its linking it now? And yes, but "actually supporting" I mean exactly that. A export const config = { amp: 'hybrid' }
, to actually be supported - css imports that are currently linked, should be inlined.
But thanks for clarifying @timneutkens - this tool _almost_ works like a charm 馃拑
I'm not sure what else to discuss here. As said Next.js supports AMP and you can't reason that it doesn't. You're reasoning "AMP doesn't work in my particular edge case".
As said it might be part of #8626.
Note that there are better solutions than css imports for creating AMP pages, like using styled-jsx / other css-in-js libraries. AMP has restrictions on the amount of css that can be sent which are very restrictive so css imports will send too much css in general.
Styled JSX throws amp-validation errors.
The mandatory attribute 'amp-custom' is missing in tag 'style amp-custom (transformed)'.
When using <style amp-custom>{'...'}</style>
in <Head>
(as it is supposed to be) it compiles in HTML as: <style amp-custom content=""></style><style>(styled JSX here)</style>
That's why this is a problem.
#8626 didn't resolve this issue for me. And the workaround failed on zeit now.
Is there a way to make this work?
Thank you
any update on this?
<Head>
<title>{title}</title>
<style amp-custom>{`body {background-color: gray;}`}</style>
</Head>
is compiled as (in prod):
<head>
<style>body {background-color: gray;}</style>
<link rel="canonical" href="/">
<style amp-custom></style>
</head>
Can you please add this future for all css, scss and css, scss modules import to work with AMP. I have wasted 3 months now. FML
@selahattintoprak feel free to send a PR to add it
hello folks, I found a solution:
_document.js
. I used tailwindcss with AMP as an example and exposed completed code in my post https://dev.to/geekplux/how-to-use-tailwindcss-with-amp-in-a-next-js-project-1f97
鈽濓笍 @geekplux's workaround worked well for me. I am not using tailwindcss, but am using styled-components, and wanted to use a global css file. To expand a bit on what it entails:
*.css
into a minified and autoprefixed *.min.css
file. This requires extending the default postcss.config.js (and a slightly different syntax because of next.js' lack of require()
s)_document.js
styles
of _document.js
Differences in my implementation:
process.env.NODE_ENV
(instead of a custom env) to differentiate prod vs dev.cssnano
to minify the css (and also named it *.min.css)Downside of this implementation:
next start
, that'd be great.Another workaround is to leverage the styled-css global feature + Next.js useAmp hook.
See blog here: https://nextjs.org/blog/styling-next-with-styled-jsx#writing-styles-in-external-files
Example usage:
import React from 'react';
import { useAmp } from 'next/amp';
import globalStyles from '../styles/global.js';
function DefaultLayout () {
const isAmp = useAmp();
return (
<div>
{isAmp && <style jsx global>
{globalStyles}
</style>
}
</div>
);
}
Downside is copying versioned files to your project.
It's a really big issue because I use tailwind and I need style AMP pages with tailwindcss classes.
Most helpful comment
Styled JSX throws amp-validation errors.
The mandatory attribute 'amp-custom' is missing in tag 'style amp-custom (transformed)'.
When using
<style amp-custom>{'...'}</style>
in<Head>
(as it is supposed to be) it compiles in HTML as:<style amp-custom content=""></style><style>(styled JSX here)</style>
That's why this is a problem.