GithubHelp home page GithubHelp logo

Comments (13)

geelen avatar geelen commented on May 4, 2024 4

Woo, found a manual escape hatch:

const Vertical = styled.g`
  && line {
    stroke-width: 1px;
  }
`

This generates .xxx.xxx line which lifts its specificity above .yyy line (from SVG above), so tbh I think this is "good enough" to consider this option closed.

In fact you can actually use && { some: thing; } to target the element itself (not just descendants). In case you have some greedy rules outside (like html p) which would override a styled.p with a single class name. This is great, since we don't have to design good JS to cover bad CSS, we can just give folks a way to generate even worse CSS 👍

from styled-components.

geelen avatar geelen commented on May 4, 2024

The above demo works now because of #29 but this one doesn't:

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

const Outer = styled.div`
  padding: 1rem;
  p {
    color: red;
  }
`

const Inner = styled.div`
  p {
    color: blue;
  }
`

const AlternateInner = styled(Inner)`
  p {
    color: green;
  }
`

export default () => (
  <div>
    {/* This causes AlternateInner to be rendered, then Inner */}
    <AlternateInner/>
    {/* Then outer gets rendered, overwriting both of them */}
    <Outer>
      <p>This should be red</p>
      <Inner>
        <p>This should be blue</p>
      </Inner>
      <AlternateInner>
        <p>This should be green</p>
      </AlternateInner>
    </Outer>
  </div>
)

image

If you drop the initial <AlternateInner/> it works:

export default () => (
  <div>
    <Outer>
      <p>This should be red</p>
      <Inner>
        <p>This should be blue</p>
      </Inner>
      <AlternateInner>
        <p>This should be green</p>
      </AlternateInner>
    </Outer>
  </div>
)

image

This is... going to be a pain to fix.

from styled-components.

geelen avatar geelen commented on May 4, 2024

Simpler example not using descendant tag selectors since those are going to hurt no matter what:

const Outer = styled.div`
  padding: 1rem;
  color: red;
`

const Inner = styled.div`
  color: blue;
`

const AlternateInner = styled(Inner)`
  color: green;
`

export default () => (
  <div>
    <AlternateInner/>
    <Outer>
      This should be red
      <Inner>
        This should be blue
      </Inner>
      <AlternateInner>
        This should be green
      </AlternateInner>
    </Outer>
  </div>
)

image

Again, commenting out <AlternateInner/> makes it work.

from styled-components.

geelen avatar geelen commented on May 4, 2024

Ah, I think componentDidUpdate will fire in the right order. So maybe we have to defer injection of the CSS until that point.

from styled-components.

mxstbr avatar mxstbr commented on May 4, 2024

So maybe we have to defer injection of the CSS until [componentDidUpdate]

Hmm, sounds like that might introduce flashes of unstyled content?

from styled-components.

geelen avatar geelen commented on May 4, 2024

I just implemented it, it doesn't seem to. I think we're good.

from styled-components.

geelen avatar geelen commented on May 4, 2024

The idea being that if you called styled(X) then Xs styles are injected before your own. That's the same guarantee composes gives you in CSS Modules.

from styled-components.

mxstbr avatar mxstbr commented on May 4, 2024

Wouldn't that break in this case?

const Comp = styled.something`
styles: here;
`;

const SomeOtherComp = styled(Comp)`
styles: overridden;
`;

// …

<SomeOtherComp>
  <SomeComp />
</SomeOtherComp>

from styled-components.

geelen avatar geelen commented on May 4, 2024

Nope, that should be fine.

from styled-components.

geelen avatar geelen commented on May 4, 2024

Interesting, by fixing the more complex case we break the original case :/

Test cases:

const SVG = styled.svg`
  line {
    stroke-width: 4px;
  }
`

const Vertical = styled.g`
  line {
    stroke-width: 1px;
  }
`

export default () => (
  <SVG>
    <line x1={10} y1={10} x2={90} y2={10}/>
    <Vertical>
      <line x1={10} y1={10} x2={90} y2={90}/>
    </Vertical>
  </SVG>
)
const Outer = styled.div`
  padding: 1rem;
  color: red;
`

const Inner = styled.p`
  color: blue;
`

const AlternateInner = styled(Inner)`
  color: green;
`

export default () => (
  <div>
    <AlternateInner/>
    <Outer>
      This should be red
      <Inner>
        This should be blue
      </Inner>
      <AlternateInner>
        This should be green
      </AlternateInner>
    </Outer>
  </div>
)

If we inject the CSS during componentWillReceiveProps we get CSS injected as Components get rendered:

image

If we wait until componentDidUpdate we get:

image

So... I think we need to actually go off the source order of the style.tagName calls then inject the CSS into that spot. Having a separate style tag for each one would work, but 😱😱😱

from styled-components.

geelen avatar geelen commented on May 4, 2024

Mind you, the only reason that SVG example breaks is because there are two descendant tag selectors (which is not good practice), so I'm going to ship the version that works for const AlternateInner = styled(Inner) (i.e. componentDidUpdate).

I did just confirm that if the styles have the right specificity then the picture is right for both examples:

image

I did that by repeating the class selectors N times where N is the order of their definition. But we can't do that in production, so we have to insert rules out-of-order. Glamor can't do that at the moment, and I'm a bit worried about the pef implications (one rule injected at the top could invalidate A LOT of styles). But if I can figure out some other approach I will.

from styled-components.

mxstbr avatar mxstbr commented on May 4, 2024

&& ≈≈ aphrodite/important – I like it!

from styled-components.

geelen avatar geelen commented on May 4, 2024

So this didn't stay solved for long. I found that server-side rendering wasn't firing the componentDidMount, so we can't use that to inject.

from styled-components.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.