Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

'Nested style detected' when dynamically including a media query in a jsx style declaration #3133

Closed
MissaouiChedy opened this issue Oct 19, 2017 · 4 comments

Comments

@MissaouiChedy
Copy link

It is in my understanding that the <style jsx> tag contains an interpolated string in order allow insertion of variables that can be stored and manipulated in javascript as in the following example:

const color = 'red';

return (<div>
    <p>Hello</p>
    <style jsx>
    {`
        p {
            color: ${color};
        }
    `}
    </style>
</div>);

I am trying to use the previous mechanism to encapsulate the media queries that I use in a single location:

    const mediaQueries = {
        mobile: '@ media screen and (max-width: 320 px)',
        ...
    };

But when I try to use them as follows:

return (<div>
    <p>Hello</p>
    <style jsx>
    {`
        ${mediaQueries.mobile} {
            p {
                color: ${color};
            }
        }
    `}
    </style>
</div>);

I get the following error:

Module build failed: Error: /absolute_path/MediaQueryIssueExample/pages/index.js?entry: Nesting detected at 9:21. Unfortunately nesting is not supported by styled-jsx.
    at Function.disableNestingPlugin (/absolute_path/MediaQueryIssueExample/node_modules/styled-jsx/dist/lib/style-transform.js:22:13)
    at proxy (/absolute_path/MediaQueryIssueExample/node_modules/stylis/stylis.js:1311:30)
    at compile (/absolute_path/MediaQueryIssueExample/node_modules/stylis/stylis.js:804:14)
    at compile (/absolute_path/MediaQueryIssueExample/node_modules/stylis/stylis.js:366:17)
    at compile (/absolute_path/MediaQueryIssueExample/node_modules/stylis/stylis.js:366:17)
    at stylis (/absolute_path/MediaQueryIssueExample/node_modules/stylis/stylis.js:1458:16)
    at transform (/absolute_path/MediaQueryIssueExample/node_modules/styled-jsx/dist/lib/style-transform.js:120:3)
    at processCss (/absolute_path/MediaQueryIssueExample/node_modules/styled-jsx/dist/_utils.js:461:65)
    at PluginPass.exit (/absolute_path/MediaQueryIssueExample/node_modules/styled-jsx/dist/babel.js:232:51)
    at newFn (/absolute_path/MediaQueryIssueExample/node_modules/babel-traverse/lib/visitors.js:276:21)

The MediaQueryIssue repository contains a minimalistic example that demonstrates the issue.

The error message indicates that nested styling as been detected, this seems odd since I did use only one <style jsx> elements inside the rendered structure of the previous example.

One of the advantages of using styled jsx is the ability to substitute values that can be manipulated in JavaScript in order to kill as much duplication as possible, unfortunately the fact that it is impossible to substitute media queries limits this advantage greatly.

I suspect that this might be a styled jsx specific issue but I am not sure yet and I thought it would better to start the discussion here.

Pointers to where to debug are welcome and I would be glad to contribute fixes if possible.

@MFCo
Copy link
Contributor

MFCo commented Oct 19, 2017

Try adding support for nesting via PostCSS. A simple solucion could be modify your package.json to something like:

{
  "name": "MediaQueryIssue",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {
    "dev": "next",
    "build": "next build",
    "start": "next start"
  },
  "dependencies": {
    "next": "^4.1.0",
    "react": "^16.0.0",
    "react-dom": "^16.0.0",
    "postcss-nested": "2.1.2",
    "styled-jsx-plugin-postcss": "0.1.0"
  },
  "postcss": {
    "plugins": {
      "postcss-nested": {}
    }
  }
}

And add a .babelrc

{
  "presets": [
    [
      "next/babel",
      {
        "styled-jsx": {
          "plugins": [
            "styled-jsx-plugin-postcss"
          ]
        }
      }
    ]
  ]
}

This should work :)

@MissaouiChedy
Copy link
Author

MissaouiChedy commented Oct 20, 2017

@MFCo thank you for your suggestion.

Unfortunately, the error is gone but the media query has no effect.

I created the .babelrc and modified package.json as you indicated, I also made sure to run npm install.

As I mentioned the nesting error is gone, the page loads properly but when I switch to the mobile view nothing changes as if there where no media query.

Here is a chunk of the generated CSS that I get when I inspect the <style> element under the page's <head>:

@media screen and (max-width: 320px).jsx-1595924628 

p.jsx-1595924628{color:blue;}

It seems that the media query is interpreted as a CSS class.

Furthermore, I tried to replace the following:

${onMobile} {
  p {
    color: blue;
  }
}

with an explicit and static media query:

@media screen and (max-width: 320px) {
  p {
    color: blue;
  }
}

Only then did it work.

@giuseppeg
Copy link
Contributor

@MissaouiChedy try to keep the value only in the variable:

@media screen and (max-width: ${mobile}) {
   p { color: blue }
}

otherwise our CSS parser doesn't have any way to tell that your interpolation is a media query .. it'd rather think that it encountered a nested block.

@MissaouiChedy
Copy link
Author

@giuseppeg thank you for your suggestion.

We started using the SCSS syntax in our styled jsx code which removed the need to wrap media queries in variables.

Now we just use SASS mixins.

@lock lock bot locked as resolved and limited conversation to collaborators Mar 16, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants