target first-child css styled-components
Asked Answered
G

6

22

I am using styled-components and want to target the first child of Text, but am unable to do so.

const Text = styled.p`
    font-size: 12px;
    &:first-child {
        margin-bottom: 20px;
    }
`;

... component

return(
   <div>
      <p>I am just regular text</p>
      <p>Me too</p>
      <Text>Hello Joe</Text> // this should have the margin bottom
      <Text>Goodbye</Text >
   </div>
)
Geoffrey answered 2/1, 2019 at 15:21 Comment(0)
H
31

Finally, I got your issue. The styled component confuses with the first two native p tag (from my perspective) and that's the reason why the CSS is not applied.

I will use a workaround like this:

const Text = styled.p`
    font-size: 12px;
    color: blue;
    &:nth-child(3) {
        margin-bottom: 20px;
        color: red !important;
    }
`;

By doing this, you are selecting the third child (which include the first two p tag) for the CSS

OR, you can do something like this: Adding a class name for the tag and giving CSS for that class.

const Text = styled.p`
  font-size: 12px;
  color: blue;
  &.colors {
    margin-bottom: 20px;
    color: red !important;
  }
`;

 <div>
    <p>I am just regular text</p>
    <p>Me too</p>
    <Text className="colors">Hello Joe</Text>
    <Text>Goodbye</Text>
</div>

Here is the demo

Hope it helps :)

Hsu answered 2/1, 2019 at 15:30 Comment(5)
I updated my question slightly, there is a span within the p tag, would that have something to do with it not working? Sorry for not including earlier. Also, when I use your code it is all in blue, so for some reason first-child not workingGeoffrey
so strange, still not working for me here. Will give ye both upvotes anywayGeoffrey
@Thinker lol I've written almost the exact same words and also provided a demo using two different colors. I think we might be css-soulmates,.. just kidding.. :DAdmixture
can you check the updated question - this is why it is offGeoffrey
@peterflanagan you are correct. Now I am getting the issue. It's becz of the first two p tag. I have updated my solutions. Hope it helps :)Hsu
S
24

Use like this

const Text = styled.p`
   font-size: 12px;
    > * {
      &:first-child {
         margin-bottom: 20px;
      }
    }
`;
Sheritasherj answered 25/11, 2020 at 6:35 Comment(2)
This works well, however updating the answer to include why it works would be extra useful.Imperishable
Is this a "because React" thing or is it a "because CSS" thing?Categorize
B
11

There shouldn't be a space between the & and the :first-child

&:first-child {
    margin-bottom: 20px;
}
Botswana answered 2/1, 2019 at 15:24 Comment(5)
that is what I thought too, and had tried this also, but it doesn't workGeoffrey
Odd. Is the font-size property is applying fine?Botswana
I updated my question slightly, there is a span within the p tag, would that have something to do with it not working? Sorry for not including earlier.Geoffrey
@Botswana is right, it was the empty space. Check this demo: Everything is working: codesandbox.io/s/8882z34y19Admixture
can you check the updated question - this is why it is offGeoffrey
T
4

it's better to use :last-of-type on certain styled component instead of using :nth-child and it works perfectly

export default styled.div`
    :last-of-type {
        background: red;
    }`

const Text = styled.p`
    font-size: 12px;
    color: blue;
    &:nth-child(3) {
        margin-bottom: 20px;
        color: red !important;
    }
`;
Tieback answered 7/12, 2019 at 12:57 Comment(1)
I like the last-of-type approach. A little more modular (e.g. component styling is kept specific to the element itself, rather than interfering with a child).Brettbretz
M
0

This is possible, but probably not correct

This totally is possible, as we see with the other answers. The issue is that with first-child or nth-child solutions you tend to end up reaching down the DOM hierarchy, creating all sorts of specificity issues that can be difficult to untangle later.

The beauty of Styled Components is you typically apply styles to the element itself, meaning your styles stay tightly coupled to your components. Components become portable, and it's easy to find the line of CSS that might be causing an issue in a complex app.

for example, if I were to style the first <a> in a list item in a ul differently, I'd need to put :first-child further up the hierarchy, breaking encapsulation.

Treat your styles as a function

The simple solution to this is to recognise that the styled component is a function that can receive parameters:

<StyledListItem index={index} />

Then receive that parameter in the component:

export const StyledListItem = styled.li<{index?: number}>`
  ${
    ({index}) => {
      if (index === 3) return `
        color: red;
        border: 2px dotted pink;
      `
      if (index === 0) return `
        border-left: none
      `
    }
  }
`

CSS in JS facilitates these kinds of programmatic solutions, and your life will be easier if you leverage them.

Maine answered 1/8, 2022 at 8:39 Comment(0)
K
-1

try using the style with the HTML tag you want to style, In your case, it would be:

p:first-child {
// your style here
}
Komsomol answered 4/9, 2023 at 14:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.