theapache64
theapache64

Reputation: 11754

Nested Text, Vertical Align not working - React Native

Ok, Let's make this simple. I've two Text components, one inside another. The first Text has fontSize of 60, and the nested one has fontSize of 20. As the font size varies, the nested Text sits base aligned. I want the nested Text vertically center aligned with the parent one.

Code

// @flow
import React, { Component } from 'react';
import { Text } from 'react-native';

type PropTypes = {}
export default class SampleVC extends Component<PropTypes> {
    render() {
        return (
            <Text style={{ fontSize: 60 }}>
                Big Text
                <Text style={{ fontSize: 20 }}>Small Text</Text>
            </Text>
        );
    }
}

Current Output

Current Ouput

Needed Output

enter image description here

I know this is a simple scenario, but as am new to react native , i can't figure it out. I've searched all over the web,but couldn't find any helpful resource.

Upvotes: 14

Views: 13005

Answers (7)

cglacet
cglacet

Reputation: 10912

That seems odd, but here is something that seems to do the job for me (using @Ali SabziNezhad's suggestion). It allows to share text props (like color) and alignement (center in this particular case)

function Component() {
    return (
        <CenterText style={{color: 'red'}}>
            Centered <Text style={{fontSize: 50}}>text</Text>
        </CenterText>
    );
}
export function CenterText({children, ...otherProps}: Text['props']) {
    return (
        <Text {...otherProps}>
            <View 
                style={{flexDirection: 'row', alignItems: 'center'}} 
                children={children} 
            />
        </Text>
    );
}

We could event have a more generic alignment text component:

export function AlignedText({children, alignItems, ...otherProps}: AlignedTextProps) {
    return (
        <Text {...otherProps}>
            <View 
                style={{flexDirection: 'row', alignItems: alignItems}} 
                children={children} 
            />
        </Text>
    );
}

type Alignment = 'baseline' | 'center' | 'flex-end' | 'flex-start' | 'stretch';
type AlignedTextProps = Text['props'] & {alignItems: Alignment};

Which we can then use to define CenterText:

export function CenterText(props: TextProps) {
    return <AlignedText alignItems='center' {...props} />;
}

Or directly as:

function Component() {
    return (
        <AlignedText style={{color: 'red'}} alignItems='center'>
            Centered <Text style={{fontSize: 50}}>text</Text>
        </AlignedText>
    );
}

Upvotes: 0

JDune
JDune

Reputation: 577

Since React-Native v0.63 you can render <View/> inside <Text/>, without providing explicit dimensions for the View. Release Notes

With the accepted answer, if your Big Text is long enough to span multiple lines, the small text will be vertically centered to the entire block of Big Text, rather than a specific line.

So here's an update to @Ali S's answer using the new functionality. Height is still required in order to vertically center the nested text, so it is set to the fontSize of the Big Text. Width can be omitted, so the length of the small text can now be dynamic.

function BigSmallText(props) {
    let bigFontSize = 40;
    return (
        <Text
            style={{
                fontSize: bigFontSize,
                lineHeight: bigFontSize,
            }}>
            A very long sentence that spans multiple lines
            <View
                style={{
                    flexDirection: 'row',
                    alignItems: 'center',
                    height: bigFontSize,
                }}>
                <Text
                    style={{
                        fontSize: 14,
                        paddingLeft: 10,
                    }}>
                    SMALL TEXT
                </Text>
                <Text
                    style={{
                        fontSize: 6,
                        paddingLeft: 10,
                    }}>
                    TINY TEXT
                </Text>
            </View>
        </Text>
    );
}

Upvotes: 1

Daniel Givoni
Daniel Givoni

Reputation: 743

you can also define the smallText lineHeight to match the bigText:

render() {
    return (
        <Text style={{ fontSize: 60 }}>
            Big Text
            <Text style={{ fontSize: 20, lineHeight:60 }}>
                Small Text
            </Text>
        </Text>
    );
}

Upvotes: 2

Alby
Alby

Reputation: 36

< View style={{flexDirection:'column'}}>


    <View style={{alignContent:'center'}}>

        <Text style={{fontSize:60}}>{props.bigText}</Text>

    </View>

    <View style={{alignContent:'center'}} >

        <Text style={{fontSize:20}}>{props.smallText}</Text>

     </View>

< /View>

Upvotes: 0

Ravi Raj
Ravi Raj

Reputation: 6677

It's not possible to achieve what you're trying using just nested Text.

The Only option, use a View to wrap your texts like,

<View style={{ flexDirection: 'row', alignItems: 'center' }} >
  <Text style={{ fontSize: 60 }}>Big Text</Text>
  <Text style={{ fontSize: 20 }}>Small Text</Text>
</View>

And if you want to use it often, create your own custom component for the above like,

function CustomNextedText (props) {
  return (
    <View style={{ flexDirection: 'row', alignItems: 'center' }} >
      <Text style={{ fontSize: 60 }}>{props.bigText}</Text>
      <Text style={{ fontSize: 20 }}>{props.smallText}</Text>
    </View>
  );
}

Use it anywhere like any other react-native component,

 <CustomNextedText bigText='Big Text' smallText='Small Text'/>

Hope it helps.

Upvotes: 14

Ali SabziNezhad
Ali SabziNezhad

Reputation: 3118

You can wrap nested Text in a View but nested View must have width and height. If you do not have any problem with this constraint, this is a good solution.

<Text style={{ fontSize: 60 }}>
      Big Text
      <View style={{ height:40, width:100, justifyContent: 'center', alignItems: 'center' }}>
            <Text style={{ fontSize: 20 }}>Small Text</Text>
      </View>
</Text>

Upvotes: 4

Nirmalsinh Rathod
Nirmalsinh Rathod

Reputation: 5186

You can add both Text into View.

<View style={{alignItems: 'center', justifyContent: 'center'}}>
       <Text style={{ fontSize: 60, height:'100%' }}>Big Text</Text>                
       <Text style={{ fontSize: 20, height:'100%' }}>Small Text</Text>
</View>

Upvotes: 0

Related Questions