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

Scoping imported CSS w/ styled-components #3281

Closed
1 task done
brandonmp opened this issue Nov 14, 2017 · 4 comments
Closed
1 task done

Scoping imported CSS w/ styled-components #3281

brandonmp opened this issue Nov 14, 2017 · 4 comments

Comments

@brandonmp
Copy link
Contributor

brandonmp commented Nov 14, 2017

I'm using babel-plugin-inline-import to import built css files for antd components. I import the CSS as strings & insert it via tagged template literal into a styled-component. This is to avoid requiring the entire CSS file on every page.

  • I have searched the issues of this repository and believe that this is not a duplicate.

Expected Behavior

When importing CSS as a string and passing it to a styled component, the imported styles should affect components in the proper scope.

Here's my .babelrc:

{
    "presets": ["next/babel"],
    "plugins": [
        [
            "styled-components",
            { "ssr": true, "displayName": true, "preprocess": false }
        ],
        [
            "inline-import",
            {
                "extensions": [".css"]
            }
        ]
    ]
}

Current Behavior

When I wrap the component in the regular styled function from styled-components, the styles are injected into the <head> and the component is given the correct classnames. However, no styles are applied.

Such an implementation looks like this:

import Button from 'antd/lib/button';
import styled from 'styled-components';
import Styles from 'antd/lib/button/style/index.css';

export default styled(Button)`
    ${Styles};
`;

^^ Note that this implementation works in non-nextjs projects, at least in my experience.

Now, when I use styled-components injectGlobal, though, it works fine:

import Button from 'antd/lib/button';
import { injectGlobal } from 'styled-components';
import Styles from 'antd/lib/button/style/index.css';

injectGlobal`${Styles}`;
export default Button;

Using classnames to style descendants work fine in Styled Components/next in regular use cases, like this:

// index.js
const Wrapper = styled.div`
  .potato {
      background: brown;
      height: 100px;
      width: 100px;
  }
`
export default props => <Wrapper><div className={'potato'}/></Wrapper>

It seems the only broken case is when I'm importing the css.

Steps to Reproduce (for bugs)

I setup a small example repo based on the with-styled-components example in next's repo:
https://github.com/brandonmp/styled-components-next-scope

Context

I'm trying to port over a project from Gatsby, and I'd rather not pollute global with all of antd's styles.

Your Environment

Tech Version
next latest
node 8.6.0
OS Win10 via WSL Bash
browser Chrome 62
etc My favorite food is pickles
@pruhstal
Copy link

I think the reason it works with injectGlobal vs putting it directly on the styled Button component is that the class scope is nested too deep when you put it on a Button.

Consider this:

You have a Button component and then import the corresponding antd styles for that component.

Those styles now get nested as such:

const WrappedButton = styled(Button)`
  .ant-btn-primary {
    background: red;
  }

When in reality, they should be this (note the &):

const WrappedButton = styled(Button)`
  &.ant-btn-primary {
    background: red;
  }

So this is why the injectGlobal works fine for you. I'd bring the issue up with the folks over @ https://github.com/styled-components to see if they have a good solution over using injectGlobal.

@brandonmp
Copy link
Contributor Author

brandonmp commented Nov 14, 2017

thanks @pruhstal. I don't believe the & is necessary in the way you've described it is. I mentioned this in OP, but this pattern works fine in other non-SSR projects (incl. Gatsby, which is sort-of SSR). I think the & is only necessary with pseudo-selectors, not regular selectors.

There's an example in the repo I set up in OP demonstrating this, but here's a webpack bin with styled-components affecting a deeply nested div in a nested component with no &:

https://www.webpackbin.com/bins/-KywGV9ZD4mUavFIORe9

Here's code:

import React from 'react'
import styled from 'styled-components'

const Wrapper = styled.div`
  .potato {
    background: blue;
    height: 100px;
    width: 100px;
}
`

const SomethingElse = props => (  <div className={'potato'}/>)


function Hello () {
  return (
    <Wrapper>
      <div>
        <div>
          <div>
            <div>
            <SomethingElse/>
            </div>
          </div>
        </div>
      </div>
      </Wrapper>
  )
}

export default Hello

@brandonmp
Copy link
Contributor Author

FWIW it appears some are experiencing similar challenges w/ styled-jsx, though I can't be sure the problem is the same:

#544 (comment)

@timneutkens
Copy link
Member

I'm expecting this to be solved now that there's universal webpack and otherwise it sounds like more of a styled-components / babel plugins issue 🤔

@lock lock bot locked as resolved and limited conversation to collaborators May 31, 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

3 participants