Adding a solid stroke to Text
Asked Answered
M

3

12

I am trying to add a thick solid stroke to some Text in React Native. I've added a snippet with the desired CSS.

I've tried directly applying the CSS via styled-components but I get an error stating that my value is unable to be parsed.

const Title = styled.Text`
  text-shadow: 2px 2px 0px  #000, -2px -2px 0px  #000, 2px -2px 0px  #000, -2px 2px 0px  #000;
`;

I have tried using textShadow but this does not apply a solid stroke. This prop relies on a width and height prop for an offset.

Here's a snack for example - https://snack.expo.io/@hannigan/ba7574

h1 {
  text-shadow: 2px 2px 0px  #000, -2px -2px 0px  #000, 2px -2px 0px  #000, -2px 2px 0px  #000;
  color: white;
  font-family: 'Arial';
}
<h1>Hello World</h1>
Margaritamargarite answered 24/2, 2020 at 13:44 Comment(0)
C
13

This works for me, are you sure that it won't work for you in dynamic height?

Edit: I might have now found what you were talking about. I am checking if I can update the snack to work for dynamic views.

Edit2: Alright, made it work. You just need to make the first text non-absolute.

https://snack.expo.io/Bk8ifP!4I

Edit3: As mentioned by Vencovsky, it might break if you need to use flex around it. You can hack it with a onLayout like in this Snack: https://snack.expo.io/HJ!PRUKNL

Basically, you save the height of the text and then use it for height and margin on other views. It's hacky, but I have used it in other settings and works fine.

example text with stroke screenshot

export default class App extends React.Component {
  render() {
    const myText = 'Hello World. This is my very long text, that can be a few lines height'

    return (
      <View style={styles.container}>
    
        <View>
          <Text style={[styles.paragraph]}>{myText}</Text>
          <Text style={[styles.paragraph, styles.abs, {textShadowOffset: {width: -2, height: -2}}]}>{myText}</Text> 
          <Text style={[styles.paragraph, styles.abs, {textShadowOffset: {width: -2, height: 2}}]}>{myText}</Text>
          <Text style={[styles.paragraph, styles.abs, {textShadowOffset: {width: 2, height: -2}}]}>{myText}</Text> 
        </View>
 
       <Text>'Here another text'</Text>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    justifyContent: 'center',
    paddingTop: Constants.statusBarHeight,
    backgroundColor: '#ecf0f1',
    padding: 8,
  },
  paragraph: {
    fontSize: 50,
    color: '#FFF',
    textShadowColor: 'black',
    textShadowRadius: 1,
    textShadowOffset: { 
      width: 2,
      height: 2,
    },
  }, 
  abs: {
    position: 'absolute',
    top: 0,
    left: 0,
    right: 0,
    bottom: 0,
  },
});
Charismatic answered 29/2, 2020 at 21:51 Comment(6)
This looks good, but if you add it around a View with some other properties, it just breakComprador
@Comprador what do you mean? A View where? Like a sibling of the shadow Text?Charismatic
Wrapping the View with the four texts, if you add flex 1 or other display props, it breaksComprador
Good point, you were right. I added a workaround with onLayout. It is hacky and not 100% perfect but oh well.Charismatic
Nice solution, changing the font size to something smaller seems to break it. Changing all 2 values to 1 adds an unwanted shadow, removing any shadow related properties breaks the solid line.Margaritamargarite
@Margaritamargarite In that case, you probably need to go with a Light font or something that would allow you to add the shadow and leave some space to avoid that. Did not try it tho.Charismatic
C
7

I couldn't find a way to do this with react native's css but I found a way to do a stoke in the text with react-native-svg

<Svg height="60" width="200">
  <Text
    fill="none"
    stroke="purple"
    fontSize="20"
    fontWeight="bold"
    x="100"
    y="20"
    textAnchor="middle"
  >
    STROKED TEXT
  </Text>
</Svg>

enter image description here

Edit

I know this answer isn't the perfect one, but so far is the only answer I found to do this, but unfortunately it isn't good for dynamic text.

Comprador answered 24/2, 2020 at 14:47 Comment(6)
I had tried this solution but is there a way to render multi-line text dynamically? Adding a paragraph of Lorem Ipsum messes everything up. The height of the SVG has to also be dynamic as content is coming back from an API.Margaritamargarite
@Margaritamargarite What you can try is implement a View with two Text inside with absolute possition where one Text is n pixels bigger than the so it looks like a borderComprador
Yeah unfortunately this was one of the only solutions I found, to have 4 Text components rendering a text-shadow and positioned absolute.Margaritamargarite
The problem with the above is that having position absolute text items means that I can't wrap a parent around it. If I know the text is going to be 2 lines I can hard code a height for the parent, but the amount of text is dynamic.Margaritamargarite
Actually I was going with that solution and that won't look fine that is why I didnt post it. The Font will somehow distort and the overlapping is not perfect.Charismatic
Alright made it work, just posted the answer. Hope it works for you too.Charismatic
H
1

If you're looking to create outlined text in React Native, check out the react-native-stroke-text package I've developed. It's straightforward and efficient.

https://github.com/charmy/react-native-stroke-text

Feedback is welcome!"

Husbandry answered 22/1, 2024 at 0:33 Comment(1)
Wow! Awesome package and its working!Rakehell

© 2022 - 2025 — McMap. All rights reserved.