Creating CSS circles in react-native

React Native

React Native Problem Overview


I'm having some trouble creating CSS circles in react-native. The following works in iPhone 6 Plus but in all the other iPhones, they become diamonds.

circle: {
  height: 30,
  width: 30,
  borderRadius: 30,
}

Now if I use PixelRatio on borderRadius it works in everything but iPhone 6 plus. iPhone 6 plus renders it as boxes with rounded corners.

circle: {
  height: 30,
  width: 30,
  borderRadius: 30 / PixelRatio.get(),
}

React Native Solutions


Solution 1 - React Native

Your border radius should be a half of width and your height. like below:

circle: {
   width: 44,
   height: 44,
   borderRadius: 44/2
}

Solution 2 - React Native

None of these fit my needs, if you need a responsive circle you can try using my solution:

Step 1: Import Dimensions (and other used elements) from react native (or add to existing imports list)

import { Dimensions, TouchableHighlight, Text } from 'react-native';

Step 2: Add your touchable element (you can calculate width or height of a device)

    <TouchableHighlight
      style = {{
        borderRadius: Math.round(Dimensions.get('window').width + Dimensions.get('window').height) / 2,
        width: Dimensions.get('window').width * 0.5,
        height: Dimensions.get('window').width * 0.5,
        backgroundColor:'#f00',
        justifyContent: 'center',
        alignItems: 'center'
      }}
      underlayColor = '#ccc'
      onPress = { () => alert('Yaay!') }
    >
      <Text> Mom, look, I am a circle! </Text>
    </TouchableHighlight>

Step 3: Enjoy your responsive circled element

React-native circle button

Solution 3 - React Native

borderRadius should be half the side of the square. So 15 in your case - no matter what pixel ratio the device has.

It works with 30 / PixelRatio.get() only for 2x retina devices, cause the result is 15. Then for iPhone 6 Plus, you indeed get a rounded box because the result is 10 (pixel ratio is 3).

I'm surprised your saying it worked on iPhone 6 Plus with 30 for a 30x30 square.

Solution 4 - React Native

If you want to make a circle that will work on any device the only thing that you should do is to give the same height and width the same value and then give the borderRadius a really high value I personally give it 1000 so it will big enough for most of the cases

circle :{
 height : 30 ,
 width :30,
 borderRadius: 1000,
}

Solution 5 - React Native

Since borderRadius style expects number as a value you can't use borderRadius: 50%. To make circle all you have to do is use your image width/height and devide it with 2. Read more here: https://github.com/refinery29/react-native-cheat-sheet

Solution 6 - React Native

Basically just need to apply same height, width and in borderRadius have to divided by 2

E.g. height : 50, width :50 borderRadius : 50/2

Just Circle

var circle = {
    height: 30,
    width: 30,
    borderRadius: 15
}    

Responsive Circle with Device Height

var circle = {
    height: Dimensions.get('window').height * 0.1,
    width: Dimensions.get('window').height * 0.1,
    borderRadius: Math.round((Dimensions.get('window').height + Dimensions.get('window').width) / 2)
}

Responsive Circle with Device Width

var circle = {
    height: Dimensions.get('window').width * 0.1,
    width: Dimensions.get('window').width * 0.1,
    borderRadius: Math.round((Dimensions.get('window').height + Dimensions.get('window').width) / 2)
}

Example Code

import React, { useEffect, useState, useRef } from 'react'
import { Dimensions, SafeAreaView, StyleSheet, Text, View } from 'react-native'

const { height, width } = Dimensions.get('window')

function roundOff(v) {
    return Math.round(v)
}

function dimensions() {

    var _borderRadius = roundOff((height + width) / 2),
        _height = roundOff(height),
        _width = roundOff(width)

    return { _borderRadius, _height, _width }
}

export default function ResponsiveCircle() {

    return (
        <SafeAreaView style={styles.container}>
            <View style={styles.circleView}>
                <Text style={styles.text}>
                    Responsive{'\n'}Circle
                </Text>
            </View>
        </SafeAreaView>
    )

}

const commonStyles = { alignItems: 'center', justifyContent: 'center', }

const styles = StyleSheet.create({
    container: { flex: 1, ...commonStyles },
    circleView: { height: dimensions()._height * 0.2, width: dimensions()._height * 0.2, borderRadius: dimensions()._borderRadius, backgroundColor: 'tan', ...commonStyles },
    text: { textAlign: 'center', lineHeight: 25, color: 'black', fontWeight: 'bold' }
})

Demo

Solution 7 - React Native

I've been using the styled-components package to style my React Native components and the easiest solution I've found is to set the border radius to a size in px larger than half of the width that the circle will ever have. It'll then default to the equivalent of a 50% border-radius for any size smaller than that.

Solution 8 - React Native

onLayout worked for me.

Calculate width and height to maintain 1:1 aspect ratio, then set borderRadius to width/2

const [circleSytle, setCircleStytle] = useState();
...
function calCircleStyle(layoutEvent) {
  let {width, height} = layoutEvent.nativeEvent.layout;
  let dim = width > height ? width : height;

  setCircleStyle({width:dim, height:dim, borderRadius:dim/2});
}

Then apply it to your view like this:

<View onLayout={calCircleStyle} style={circleStyle}>
...
</View>

Btw, can anyone explain why borderRadius:1000 is bad?

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestioncgarvisView Question on Stackoverflow
Solution 1 - React NativejsinaView Answer on Stackoverflow
Solution 2 - React NativeBenjiView Answer on Stackoverflow
Solution 3 - React NativeJean RegisserView Answer on Stackoverflow
Solution 4 - React NativeMani SalehiView Answer on Stackoverflow
Solution 5 - React NativeAbiolaView Answer on Stackoverflow
Solution 6 - React NativeHardik DesaiView Answer on Stackoverflow
Solution 7 - React NativeDustin GaudetView Answer on Stackoverflow
Solution 8 - React NativeLjavuras.pyView Answer on Stackoverflow