chakra-ui-docs icon indicating copy to clipboard operation
chakra-ui-docs copied to clipboard

Element “style” not allowed as child of element “div” in this context.

Open nbouvrette opened this issue 2 years ago • 25 comments

Description

When I use the W3C validator I expect to get no errors but there are many errors with misplaced "style" elements

Link to Reproduction

https://validator.w3.org/nu/?doc=https%3A%2F%2Fchakra-ui.com%2F

Steps to reproduce

  1. Go to https://validator.w3.org/nu/?doc=https%3A%2F%2Fchakra-ui.com%2F
  2. Click check the Element “style” not allowed as child of element “div” in this context.

Chakra UI Version

Latest

Browser

Not applicable

Operating System

  • [X] macOS
  • [ ] Windows
  • [ ] Linux

Additional Information

As per https://github.com/validator/validator/issues/489, using <style> tags outside <head> is not following the HTML5 specifications.

There is a risk that by not following the HTML5 specifications, SEO can be impacted (see https://www.elegantthemes.com/blog/wordpress/how-to-use-w3c-validator-to-improve-seo)

As per Emotion's documentation, it looks like it is possible to move the <style> tag inside the <head>: https://emotion.sh/docs/ssr#nextjs

nbouvrette avatar May 22 '22 17:05 nbouvrette

@segunadebayo : watching this issue. Is there a timeline on a fix from Chakra-UI?

Thanks!

dube25 avatar Jun 04 '22 13:06 dube25

This is coming from the imported static font assets in _document.tsx. The link element gets handled correctly on render, but indeed emotion is adding a JS bundle style inside the body.

Per some digging though, there is already a FontFace component that looks to be importing these fonts in _app.tsx. Simply removing the link in _document.tsx does not change the rendering of this font, and will subsequently remove the rendered bundle that is causing this validation error. Running a build also does show an impact of the rendering of this font.

Does the link import need to be there in _document.tsx?

TylerAPfledderer avatar Jun 04 '22 15:06 TylerAPfledderer

@TylerAPfledderer just to clarify, I opened this issue using chakra-ui.com as an example but this impacts anyone using Chakra-UI. It looks overall like Chakra's implementation of Emotions is not following the documentation found here https://emotion.sh/docs/ssr#nextjs

nbouvrette avatar Jun 04 '22 19:06 nbouvrette

Agreed. What's missing is the inclusion of the server and css packages.

@nikolovlazar and/or @segunadebayo has this been addressed previously?

TylerAPfledderer avatar Jun 04 '22 19:06 TylerAPfledderer

Let me try to explain what's happening here:

With our current setup and approach, during SSR, emotion will render style tags inline as a sibling of any Chakra component. After hydration, emotion will move the styles to the head as fast as it can to prevent FOUC (flash of unstyled content)

If we implemented the SSR setup recommended by emotion docs, we'll skip that hydration step and extract all the styles to the head ahead of time. I think we should attempt to do this within our docs @nikolovlazar @TylerAPfledderer. If we notice improvements from this, we'll update our documentation to reflect this.

When you use markup validators, they'll run against the SSR output of the website and will see inline style as invalid, when in fact, that's not the full story.

segunadebayo avatar Jun 05 '22 07:06 segunadebayo

I did some testing (used this example), but the style tags are still prepended before each element. Will have this issue on mind, but for now I think we can close this issue since it's related to how Emotion works.

nikolovlazar avatar Jun 05 '22 09:06 nikolovlazar

@nikolovlazar @segunadebayo @TylerAPfledderer hey guys, I just did a test using the same example (npx create-next-app --example with-emotion-vanilla with-emotion-vanilla-app) - I don't see any inline style tags?

Do you mind elaborating on what you did exactly? If I a missing something I want to open an issue on the Emotion repo.

nbouvrette avatar Jun 05 '22 14:06 nbouvrette

@nbouvrette mark a page to use SSR, open it and open the "Page Source" (not Inspect Element). You'll see style tags sprinkled around the page: image

nikolovlazar avatar Jun 05 '22 14:06 nikolovlazar

@nikolovlazar I've already validated the source in W3C, also beautified the output, and do not see any inline style.

What do you mean by mark a page to use SSR - Next.js uses SSR everywhere

I do see the CSS in the <head> element.

nbouvrette avatar Jun 05 '22 14:06 nbouvrette

@nbouvrette make sure to use useServerSideProps in your page. That marks that page to use SSR.

nikolovlazar avatar Jun 05 '22 14:06 nikolovlazar

Oh ok @nikolovlazar I thought you were talking about the rendered HTML, sorry about that.

But I did try to add the following code in the example's index.js:

export async function getServerSideProps(context) {
  return {
    props: {}, // will be passed to the page component as props
  };
}

I am getting the same result in the source code - CSS inside the <head> element - what am I missing?

nbouvrette avatar Jun 05 '22 14:06 nbouvrette

@nbouvrette do you have any components inside of your page? Try reproducing this with codesandbox or stackblitz and share it with me so I can take a better look.

nikolovlazar avatar Jun 05 '22 14:06 nikolovlazar

@nikolovlazar I was just using the vanilla example (npx create-next-app --example with-emotion-vanilla with-emotion-vanilla-app) - I can try to create components to see if this changes anything.

nbouvrette avatar Jun 05 '22 14:06 nbouvrette

Yeah please do. The style tags that we're talking about come from the components themselves. If there are no components, no style tags will be present. Add various stuff on that page and check it out again. The screenshot I sent above is from Chakra UI's index page.

nikolovlazar avatar Jun 05 '22 15:06 nikolovlazar

I just tried adding aFooter component and I still can't reproduce the inline style - the example code can be found here:

https://github.com/nbouvrette/emotion-inline-css-issue

I'm not too sure what else to try unless you have ideas?

nbouvrette avatar Jun 05 '22 15:06 nbouvrette

@nikolovlazar by the way can we re-open this issue until we pinpoint the root cause? It's still not clear to me what is causing this

nbouvrette avatar Jun 05 '22 16:06 nbouvrette

FYI I tried to re-add all the different style types into the component to see if it was not a specific Emotion feature that triggered the issue and the CSS was still not inline.

@nikolovlazar @segunadebayo @TylerAPfledderer could we please re-open this issue and if you have any suggestions on how to try to reproduce it in this repo: https://github.com/nbouvrette/emotion-inline-css-issue

nbouvrette avatar Jun 06 '22 13:06 nbouvrette

@nikolovlazar @segunadebayo @TylerAPfledderer any ideas on how I could try to reproduce this in my repo? I might have time to investigate this weekend if you guys can give me some pointer on what could be different in Chakra

nbouvrette avatar Jun 10 '22 16:06 nbouvrette

I've made a few tests this weekend and it looks like as soon as I add _app.js with the following code, the inline CSS seems to appear right away:

import { ChakraProvider } from '@chakra-ui/react';

function MyApp({ Component, pageProps }) {
  return (
    <ChakraProvider>
      <Component {...pageProps} />
    </ChakraProvider>
  );
}

export default MyApp;

This seems a bit different than the implementation in npx create-next-app --example with-emotion-vanilla with-emotion-vanilla-app - should I try to open an issue with Emotion to see if this is expected?

nbouvrette avatar Jun 13 '22 00:06 nbouvrette

I found this issue as I try to get my NextJS project with Chakra UI to validate. I have basicly currently just followed NextJS initialization, then followed Chakra UI documentation "Getting Started with NextJS". My _app.js is same as nbouvrette showed in comment above (same that comes from Chakra documentation). I don't have _document.js in my project.

Validation is tried after I have done next build && next export and then used surge.sh to deploy this test.

I'd expect that at this point, basic "Hello world!" index would be valid, as I have followed documentation this far.

https://github.com/chakra-ui/chakra-ui-docs/issues/644#issuecomment-1146753917 comment from @segunadebayo though sounds that current behavior is correct and acceptable... If that's the case, I'd like to hear some reference where it is stated that invalid html code is fine to output, and that it doesn't have any bad side effects to SEO or usability of the site.

kerbe avatar Jul 15 '22 11:07 kerbe

@kerbe I don't know if you looked at the links I provided, (for example this one from the W3C validator), but <style> tags inside the<body> does not follow HTML specifications.

This means that it could (or could not) have any side-effect.. it really depends on how people followed the specifications. And if it doesn't have any impact today it doesn't mean it won't have any tomorrow.

Knowing all this, and also that there are ways to make this work with Emotion (see npx create-next-app --example with-emotion-vanilla with-emotion-vanilla-app), I still don't understand how we cannot reproduce the same behavior with Chakra. I'm not a Chakra or Emotion expert so I only did a basic investigation but if you have more knowledge than me on the topic, I would like to understand why this is happening.

nbouvrette avatar Jul 17 '22 11:07 nbouvrette

@nbouvrette I did go through links from you and from others, and I tried as well creating Next app with just Emotion, and it doesn't cause similar behavior as with Next with Chakra. Unfortunately I have most likely even less experience with Chakra and Emotion than you, setting up my first project with Chakra (as I heard good things from it). But as I was setting my CI/CD, which includes html5validation, stuff breaks immediately because of these errors.

As this issue has been opened in Chakra UI Docs repo, instead of actual Chakra UI repo, I wonder is that reason why this hasn't got more attention from devs, either helping to debug it, or fixing it... but then again, this is right place, if it is just problem in Chakra's docs, how it should be included with NextJS...

If there is anything we could do, it would be great to hear that @chakra-ui !

kerbe avatar Jul 18 '22 17:07 kerbe

This problem also makes Chakra to not support AMP, as it gives the following error: The parent tag of tag 'style amp-custom' is 'section', but it can only be 'head'

There are other issues when using Chakra with AMP like: Custom JavaScript is not allowed.

naman-ali avatar Aug 03 '22 13:08 naman-ali

Hi! This issue has been automatically marked as stale because lack of recent activity. It will be closed if no further activity occurs within 5 days. Thank you for your contributions.

stale[bot] avatar Sep 21 '22 03:09 stale[bot]

@nikolovlazar @segunadebayo @TylerAPfledderer any update on this issue? Just got a notification that it's about to be auto-archived.

nbouvrette avatar Sep 21 '22 13:09 nbouvrette

Hi! This issue has been automatically marked as stale because lack of recent activity. It will be closed if no further activity occurs within 5 days. Thank you for your contributions.

stale[bot] avatar Oct 30 '22 12:10 stale[bot]

Still no news on this one?

nbouvrette avatar Oct 30 '22 14:10 nbouvrette

After looking at this with @segunadebayo we found that using @emotion/styled (which is what we use under the hood) results in placing the <style> tags right next to the component. There is a way to fix this issue and put all of the styles in the <head>, but that includes overriding Next.js's server and opting out of all of the Next.js Optimizations.

Overriding the Next.js Server: https://nextjs.org/docs/advanced-features/custom-server A reproduction repo that we made: https://github.com/nikolovlazar/emotion-vanilla-ssr

I'm closing this issue because there's nothing to do at this moment. Sorry.

nikolovlazar avatar Nov 01 '22 09:11 nikolovlazar

Thanks @nikolovlazar and @segunadebayo.

I am sure what you did exactly on your reproduction repo? it looks like you simply cloned npx create-next-app --example with-emotion-vanilla with-emotion-vanilla-app - I don't see any custom-server code on there and of course, this wouldn't be a viable solution.

Regarding your comment about @emotion/styled, I was finally able to reproduce the issue. Basically, as soon as I use @emotion/styled, the CSS is left inline: https://github.com/nbouvrette/emotion-inline-css-issue

But what I am still confused about is that Chakra uses @emotion/css and not @emotion/styled? Can you share more details on how to reproduce this issue using @emotion/css because if Chakra does not use @emotion/styled, then it surely isn't the cause of the issue in this thread and I am unable to continue the investigation with Emotion.

I think it might be good to leave this issue open in the meantime until we understand what is going on?

nbouvrette avatar Nov 02 '22 17:11 nbouvrette

@nikolovlazar @segunadebayo @TylerAPfledderer any update on my last comment? I'm just looking for a clear explanation of what is causing this so that I can propose ideas... right now it's unclear still and the issue is closed again :(

nbouvrette avatar Nov 04 '22 11:11 nbouvrette