0

For some reason I'm having a rendering issue when it comes to implementing content in a :before or :after pseudo element. Given the stripped down component:

import React from 'react';
import PropTypes from 'prop-types';
import styled from 'styled-components';

const Container = styled.div`
  display: block;
  padding: 1rem;
`;

const Foo = styled.p`
  &:before {
    content: '\201C';
    display: block;
    font-size: 4rem;
    font-weight: bold;
    height: 4.25rem;
  }

  &:after {
    content: '\201D';
    display: block;
    font-size: 4rem;
    font-weight: bold;
    height: 2.625rem;
  }

  font-weight: bold;
`;

function Test({ txt }) {
  return (
    <Container>
      <Foo>{txt}</Foo>
    </Container>
  );
}

Test.propTypes = {
    txt: PropTypes.string.isRequired,
};

export default Test;

Nothing gets rendered. Referencing this answer from How to render pseudo before content dynamically in styled-component I tried:

const Foo = styled.p`
  &:before {
    content: '\201C';
    display: block;
    font-size: 4rem;
    font-weight: bold;
    height: 4.25rem;
  }

  &:after {
    content: '\201D';
    display: block;
    font-size: 4rem;
    font-weight: bold;
    height: 2.625rem;
  }

  font-weight: bold;
`;

This answer recommends double colons from Can anyone tell me why before not working on styled components?:

const Foo = styled.p`
  &::before {
    content: '\201C';
    display: block;
    font-size: 4rem;
    font-weight: 700;
    height: 4.25rem;
  }

  &::after {
    content: '\201D';
    display: block;
    font-size: 4rem;
    font-weight: bold;
    height: 2.625rem;
  }

  font-weight: bold;
`;

but I'm unable to render a before or after. Further research I've seen where content might be an issue but I'm referencing them correctly per Double Quotation and a height or width should be declared and I've made sure to pass a height in rem.

Using Styled Components version "^5.3.5", I've removed my cache, dumped the public directory and I've tested in Chrome and Firefox but I'm unable to render quotes.

Research

What am I doing wrong and how can I render pseudo elements?

DᴀʀᴛʜVᴀᴅᴇʀ
  • 7,681
  • 17
  • 73
  • 127

4 Answers4

3

EDITED:

@zharkov-ruslan is correct. You need to escape the \ in the content property. The following works:


const Foo = styled.p`
    font-weight: bold;

    &::before {
        content: "\\201C";
        display: block;
        font-size: 4rem;
        font-weight: 700;
        height: 4.25rem;
    }
    &::after {
        content: "\\201D";
        display: block;
        font-size: 4rem;
        font-weight: bold;
        height: 2.625rem;
    }
`;

In addition to just inserting the actual character as a string, you can also use the CSS keywords open-quote and close-quote.


const Foo = styled.p`
    font-weight: bold;

    &::before {
        content: open-quote;
        display: block;
        font-size: 4rem;
        font-weight: 700;
        height: 4.25rem;
    }
    &::after {
        content: close-quote;
        display: block;
        font-size: 4rem;
        font-weight: bold;
        height: 2.625rem;
    }
`;

jme11
  • 17,134
  • 2
  • 38
  • 48
  • That is wrong though and errors out. The later solution is an interesting approach and I learned something new but if you go by the first approach of terminating the quotes it causes an error. – DᴀʀᴛʜVᴀᴅᴇʀ Oct 24 '22 at 18:00
  • Hmmm... I don't get any errors when I escape the quotes and it renders the characters properly, so I'm going to leave this here for others. Happy though that you have other options to solve the problem! – jme11 Oct 24 '22 at 18:06
  • 1
    ah it looks like it might be an ESLint error, debugging now, but I was able to figure it out, I needed to terminate the backslash. Did upvote for the second half was unaware you could do that. – DᴀʀᴛʜVᴀᴅᴇʀ Oct 24 '22 at 18:06
  • Cool, and yes, it does appear to be the \ that needs to be escaped. – jme11 Oct 24 '22 at 18:09
1

Probably something is wrong with your content property inside the pseudo elements, I changes values in that fields and styles worked fine with &:before, &:after.

const Foo = styled.p`
  &:before {
    content: "“";
    display: block;
    font-size: 4rem;
    font-weight: 700;
    height: 4.25rem;
  }

  &:after {
    content: "”";
    display: block;
    font-size: 4rem;
    font-weight: bold;
    height: 2.625rem;
  }

  font-weight: bold;
`;

  • I could see that approach to resolve the issue temporarily but shouldn't `content` allow the defined code? – DᴀʀᴛʜVᴀᴅᴇʀ Oct 24 '22 at 17:49
  • It allows to use approach from @jme11 mentioned before with `\\201D`. For me it worked too. I checked it via CodeSandbox. Seems that using \\ works for styled-components, because with the plain CSS it works fine with your posted code: `\201D`. I think the trick is related to template literals in JavaScript. – Zharkov Ruslan Oct 24 '22 at 19:00
1

The hardcoded approach from this answer:

&:before {
    content: "“";
    display: block;
    font-size: 4rem;
    font-weight: 700;
    height: 4.25rem;
  }

  &:after {
    content: "”";
    display: block;
    font-size: 4rem;
    font-weight: bold;
    height: 2.625rem;
  }

works as a temporary solution but wasn't the desired course of action because I wanted to know why the code wouldn't be allowed.

The answer suggesting

You need to escape the quotes.

const Foo = styled.p`
    font-weight: bold;

    &::before {
        content: "\\201C\";
        display: block;
        font-size: 4rem;
        font-weight: 700;
        height: 4.25rem;
    }
    &::after {
        content: "\\201D\";
        display: block;
        font-size: 4rem;
        font-weight: bold;
        height: 2.625rem;
    }
`;

is wrong. The issue was escaping the backslash (\). If you escape the quotes then it errors out. As mentioned in other Q&As the preferred approach is to also use single quotes.

Solution to resolve the issue with the code was to terminate the backslash:

const Foo = styled.p`
    font-weight: bold;

    &::before {
        content: '\\201C';
        display: block;
        font-size: 4rem;
        font-weight: 700;
        height: 4.25rem;
    }
    &::after {
        content: '\\201D';
        display: block;
        font-size: 4rem;
        font-weight: bold;
        height: 2.625rem;
    }
`;

DᴀʀᴛʜVᴀᴅᴇʀ
  • 7,681
  • 17
  • 73
  • 127
0

I usually do this when I'm using pseudo elements:

  • 'position: relative' on parent.
  • 'position: absolute' on the child element.
  • I'm somewhat unsure how this answers the question? – DᴀʀᴛʜVᴀᴅᴇʀ Oct 24 '22 at 18:05
  • This is my first answer to a stack overflow question, so I may not have done it perfectly. However, I looked at the question from my CSS perspective. Generally, when adding pseudo-elements it's good to use a CSS property called "position". You can set the position to a "relative" in the parent element and use the position "absolute" in the child element. https://developer.mozilla.org/en-US/docs/Web/CSS/::before – Kushal Dhakal Oct 24 '22 at 18:23
  • um I still dont know how that would resolve the issue to the question. – DᴀʀᴛʜVᴀᴅᴇʀ Oct 24 '22 at 19:49