91

Hi am trying to set a shadow for my fab but my attempts has failed so far i tried setting shadow props but that is for ios only so i tried to play with elevation property but it doesn't look right.

Here's what i tried

  <View
    style={{
      width: 56,
      height: 56,
      elevation: 2,
      borderRadius: 28,
      marginBottom: 3,
      backgroundColor: 'rgba(231,76,60,1)',
    }}
  ></View>

What i need to achieve

enter image description here

Bhavya Koshiya
  • 1,262
  • 2
  • 8
  • 22
Ibrahim Ahmed
  • 2,295
  • 4
  • 21
  • 35

22 Answers22

150

Adding the CSS property elevation: 1 renders shadow in Android without installing any 3rd party library.

elevation is an Android-only style property available on the View elements.

See: React Native Docs for the elevation style property


If you're open to 3rd party software, another way to get shadows for android is to install react-native-shadow.

Example (adapted from the readme):

import React, { Component } from "react";
import { TouchableHighlight } from "react-native";

import { BoxShadow } from "react-native-shadow";

export default class ShadowButton extends Component {
  render() {
    const shadowOpt = {
      width: 160,
      height: 170,
      color: "#000",
      border: 2,
      radius: 3,
      opacity: 0.2,
      x: 0,
      y: 3,
      style: { marginVertical: 5 }
    };

    return (
      <BoxShadow setting={shadowOpt}>
        <TouchableHighlight
          style={{
            position: "relative",
            width: 160,
            height: 170,
            backgroundColor: "#fff",
            borderRadius: 3,
            // marginVertical: 5,
            overflow: "hidden"
          }}
        >
          ...
        </TouchableHighlight>
      </BoxShadow>
    );
  }
}
Reed Dunkle
  • 3,408
  • 1
  • 18
  • 29
FuzzyTree
  • 32,014
  • 3
  • 54
  • 85
114

The elevation style property on Android does not work unless backgroundColor has been specified for the element.

Android - elevation style property does not work without backgroundColor

Example:

{
  shadowColor: 'black',
  shadowOpacity: 0.26,
  shadowOffset: { width: 0, height: 2},
  shadowRadius: 10,
  elevation: 3,
  backgroundColor: 'white'
}
Asad Ullah
  • 1,139
  • 1
  • 7
  • 6
81

Another solution without using a third-party library is using elevation.

Pulled from react-native documentation. https://facebook.github.io/react-native/docs/view.html

(Android-only) Sets the elevation of a view, using Android's underlying elevation API. This adds a drop shadow to the item and affects z-order for overlapping views. Only supported on Android 5.0+, has no effect on earlier versions.

elevation will go into the style property and it can be implemented like so.

<View style={{ elevation: 2 }}>
    {children}
</View>

The higher the elevation, the bigger the shadow. Hope this helps!

Ajackster
  • 1,724
  • 1
  • 12
  • 12
  • why elevation attribute is written inside 2 braces? – divine Jun 24 '17 at 07:52
  • 8
    @divine the outer bracket is for JS interpolation, the inner is for an object – Asaf David Jun 25 '17 at 07:28
  • 4
    This only does a shadow on the bottom of a view, it doesn't allow you to do shadows on the other sides – Erich Aug 31 '17 at 18:41
  • Correct, there are many things iOS handles better when using react-native and shadows are one of them. – Ajackster Aug 31 '17 at 20:25
  • 5
    Be careful with `elevation` though – like it says in the docs, it "affects z-order for overlapping views" – it basically acts like a `zIndex` that you can't override and can cause really confusing behaviours. For example, in a SectionList with sticky section headers, if you put `elevation: 3` on the items in the list they will suddenly start going _over_ the headers, hiding them from view (on android only of course). This is nearly impossible to debug! – omnikron Jan 29 '18 at 16:16
  • This will work for all android version. https://github.com/Kishanjvaghela/react-native-cardview – Kishan Vaghela Jul 03 '19 at 07:08
48

You can try

//ios    
shadowOpacity: 0.3,
shadowRadius: 3,
shadowOffset: {
    height: 0,
    width: 0
},
//android
elevation: 1
Guy
  • 2,883
  • 1
  • 32
  • 39
lam luu
  • 792
  • 9
  • 7
  • 3
    Elevation does not create a large enough or configurable shadow for android - react-native-shadow seems like the best option – evanjmg Mar 06 '18 at 12:02
12

The following will help you to give each Platform the styling you want:

import { Text, View, Platform } from 'react-native';

......
<View style={styles.viewClass}></View>
......


const styles = {
viewClass: {
    justifyContent: 'center',
    alignItems: 'center',
    height: 60,
    ...Platform.select({
        ios: {
            shadowColor: '#000',
            shadowOffset: { width: 0, height: 2 },
            shadowOpacity: 0.2,
        },
        android: {
            elevation: 1

        },
      }),
}
};
Mohammed Alawneh
  • 306
  • 9
  • 22
7

for an android screen you can use this property elevation.

for example :

 HeaderView:{
    backgroundColor:'#F8F8F8',
    justifyContent:'center',
    alignItems:'center',
    height:60,
    paddingTop:15,

    //Its for IOS
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 2 },
    shadowOpacity: 0.2,

    // its for android 
    elevation: 5,
    position:'relative',

},
Mahdi Bashirpour
  • 17,147
  • 12
  • 117
  • 144
Aras
  • 1,599
  • 15
  • 25
6

You can use my react-native-simple-shadow-view

  • This enables almost identical shadow in Android as in iOS
  • No need to use elevation, works with the same shadow parameters of iOS (shadowColor, shadowOpacity, shadowRadius, offset, etc.) so you don't need to write platform specific shadow styles
  • Can be used with semi-transparent views
  • Supported in android 18 and up
RoyBS
  • 1,241
  • 16
  • 16
5

Just use 'elevation' property to get shadow in android. something like below

const Header = () => {
    // const { textStyle, viewStyle } = styles;
    return (
      <View style={styles.viewStyle}>    
        <Text style={styles.textStyle}>Albums</Text>
      </View>
    )
}


const styles = {
    viewStyle:{
        backgroundColor:'#f8f8f8',
        justifyContext:'center',
        alignItems: 'center',
        padding:16,
        elevation: 2
    }
}
SameerShaik
  • 488
  • 2
  • 10
  • 22
5

I added borderBottomWidth: 0 and it worked fine for me in android.

Sahitya D
  • 154
  • 3
  • 10
4

Also i'd like to add that if one's trying to apply shadow in a TouchableHighlight Component in which child has borderRadius, the parent element (TouchableHighlight) also need the radius set in order to elevation prop work on Android.

Andrei Vedovato
  • 171
  • 1
  • 6
3

I have implemented CardView for react-native with elevation, that support android(All version) and iOS. Let me know is it help you or not. https://github.com/Kishanjvaghela/react-native-cardview

import CardView from 'react-native-cardview'
<CardView
          cardElevation={2}
          cardMaxElevation={2}
          cornerRadius={5}>
          <Text>
              Elevation 0
          </Text>
</CardView>

enter image description here

Kishan Vaghela
  • 7,678
  • 5
  • 42
  • 67
3

In short, you can't do that in android, because if you see the docs about shadow only Support IOS see doc

The best option you can install 3rd party react-native-shadow

2

Generating shadows for a circle, react native, android

Based on the answers here, and on text that I found in github (react-native-shadow), I made few tests and thought that some people may find the following helpful.

Here is how the screen looks like:

enter image description here

Code:

import React, { Component } from 'react';
import { View, TouchableHighlight, Text } from 'react-native';
import { BoxShadow } from 'react-native-shadow'

export default class ShadowsTest extends Component {

  render() {
    const shadowOpt = {
      width: 100,
      height: 100,
      color: "#000",
      border: 2,
      radius: 50,
      opacity: 0.8,
      x: 3,
      y: 3,
      //style: { marginVertical: 5 }
    }

    return (
      <View style={{ flex: 1 }}>
        <Header
          text={"Shadows Test"} />

        <View style={{ flexDirection: 'row', justifyContent: 'center' }}>
          <View style={{ margin: 10, alignItems: 'center',
              justifyContent: 'center' }}>
            <TouchableHighlight style={{
              position: 'relative',
              width: 100,
              height: 100,
              backgroundColor: "#fff",
              borderRadius: 50,
              borderWidth: 0.8,
              borderColor: '#000',
              // marginVertical:5,
              alignItems: 'center',
              justifyContent: 'center',
              overflow: "hidden" }}>
              <Text style={{ textAlign: 'center' }}>
                0: plain border
              </Text>
            </TouchableHighlight>
          </View>

          <View style={{ margin: 10, alignItems: 'center',
              justifyContent: 'center' }}>
            <BoxShadow setting={ shadowOpt }>
              <TouchableHighlight style={{
                position: 'relative',
                width: 100,
                height: 100,
                backgroundColor: "#fff",
                borderRadius: 50,
                borderWidth: 1,
                borderColor: '#aaa',
                // marginVertical:5,
                alignItems: 'center',
                justifyContent: 'center',
                overflow: "hidden" }}>
                <Text style={{ textAlign: 'center' }}>
                  1: RN shadow package
                </Text>
              </TouchableHighlight>
            </BoxShadow>
          </View>
        </View>

        <View style={{ flexDirection: 'row', justifyContent: 'center' }}>
          <View style={{ margin: 10, alignItems: 'center',
              justifyContent: 'center' }}>
              <TouchableHighlight style={{
                position: 'relative',
                width: 100,
                height: 100,
                backgroundColor: "#fff",
                borderRadius: 50,
                borderWidth: 1,
                borderColor: '#aaa',
                // marginVertical:5,
                alignItems: 'center',
                justifyContent: 'center',
                overflow: "hidden",
                shadowOffset: { width: 15, height: 15 },
                shadowColor: "black",
                shadowOpacity: 0.9,
                shadowRadius: 10,
               }}>
                <Text style={{ textAlign: 'center' }}>
                  2: vanilla RN: shadow (may work on iOS)
                </Text>
              </TouchableHighlight>
          </View>
          <View style={{ margin: 10, alignItems: 'center',
              justifyContent: 'center' }}>
              <TouchableHighlight style={{
                position: 'relative',
                width: 100,
                height: 100,
                backgroundColor: "#fff",
                borderRadius: 50,
                borderWidth: 1,
                borderColor: '#aaa',
                // marginVertical:5,
                alignItems: 'center',
                justifyContent: 'center',
                overflow: "hidden",
                elevation: 15,
               }}>
                <Text style={{ textAlign: 'center' }}>
                  3: vanilla RN: elevation only (15)
                </Text>
              </TouchableHighlight>
          </View>
        </View>

        <View style={{ flexDirection: 'row', justifyContent: 'center', marginBottom: 30 }}>
          <View style={{ margin: 10, alignItems: 'center',
              justifyContent: 'center' }}>
              <TouchableHighlight style={{
                position: 'relative',
                width: 100,
                height: 100,
                backgroundColor: "#fff",
                borderRadius: 50,
                borderWidth: 1,
                borderColor: '#aaa',
                // marginVertical:5,
                alignItems: 'center',
                justifyContent: 'center',
                overflow: "hidden",
                elevation: 5,
               }}>
                <Text style={{ textAlign: 'center' }}>
                  4: vanilla RN: elevation only (5)
                </Text>
              </TouchableHighlight>
          </View>
          <View style={{ margin: 10, alignItems: 'center',
              justifyContent: 'center' }}>
              <TouchableHighlight style={{
                position: 'relative',
                width: 100,
                height: 100,
                backgroundColor: "#fff",
                borderRadius: 50,
                borderWidth: 1,
                borderColor: '#aaa',
                // marginVertical:5,
                alignItems: 'center',
                justifyContent: 'center',
                overflow: "hidden",
                elevation: 50,
               }}>
                <Text style={{ textAlign: 'center' }}>
                  5: vanilla RN: elevation only (50)
                </Text>
              </TouchableHighlight>
          </View>
        </View>
      </View>
    )
  }
}
Yossi
  • 5,577
  • 7
  • 41
  • 76
2

For some reason it only worked for my by adding borderColor: 'transparent' (or any other color). My style output looks like this:

{
        borderColor: "transparent", // Required to show shadows on Android for some reason !?!?
        shadowColor: '#000',
        shadowOffset: {
          width: 0,
          height: 0,
        },
        shadowOpacity: 0.3,
        shadowRadius: 5,

        elevation: 15,
      }
Michael Falck Wedelgård
  • 2,943
  • 1
  • 27
  • 39
2

A simple solution is this one!

Click here to see preview of simple drop shadow

Does not flicker when rendering collapse elements:

    const styles = {
        simpleShadow: {
            borderTopWidth: 0.5,
            borderRightWidth: 1,
            borderBottomWidth: 1,
            borderLeftWidth: 0.5,
            borderTopColor: 'rgba(0,0,0,0.1)',
            borderRightColor: 'rgba(0,0,0,0.2)',
            borderBottomColor: 'rgba(0,0,0,0.2)',
            borderLeftColor: 'rgba(0,0,0,0.1)',

            backgroundColor: 'white',
            margin: 10,
            padding: 10,
            borderRadius: 10
        }
    }
    return (
        <View style={styles.simpleShadow}>
            <Text>Simple Shadow</Text>
        </View>
    );
Christian
  • 21
  • 2
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Apr 28 '22 at 08:37
2

The react-native-shadow library is already mentioned in the answers, but it seems to be abandoned for several years.

A modern alternative, which solved my issue with consistent shadows across both iOS and Android was react-native-shadow-2.

EDIT: I ended up using the native shadow solutions (and elevation for Android). According to the docs, Android API 28 and above supports shadowColor on elevated elements and it works well for my case.

Dimitar Spassov
  • 2,535
  • 2
  • 7
  • 17
  • What do you mean by it does not look "natural" – OneTuskedMario Oct 10 '22 at 03:08
  • It looks really different from the iOS shadow or even web CSS shadow. To me it seems like a glowing outline around the element. Let me say that this doesn't mean the library cannot be used, it just didn't provide the styles I was looking for. – Dimitar Spassov Oct 10 '22 at 06:39
  • Pretty sure it's all about fine-tuning the settings and props until you get something that looks normal – OneTuskedMario Oct 10 '22 at 16:42
  • Yes, possible. I feel I lacked some controls for tweaking stuff like blur & spread radius (coming from web), which was somehow possible with the iOS-supported shadow props in ReactNative. Anyways, I edited my answer to avoid potential misleading. – Dimitar Spassov Oct 11 '22 at 05:32
1

elevation still no work in Expo v30 && React-native v0.55.4. I have tried the all answers here.

Also, don't try react-native-shadow - their shadow rendering is terrible. So, I am continuing the research.

nlavr
  • 626
  • 5
  • 7
1

Set elevation: 3 and you should see the shadow in bottom of component without a 3rd party lib. At least in RN 0.57.4

C-lio Garcia
  • 652
  • 8
  • 17
1

I had the same problem shadow/elevation not showing on Android with elevation:2. Then i noticed that the view element is fool width, so I added margin:2 to the view element and elevation properly appeared.

Style:

    margin: 2,
    shadowColor: '#000',
    shadowOffset: {
      width: 0,
      height: 1
    },
    shadowOpacity: 0.2,
    shadowRadius: 1.41,
    elevation: 2

Android: enter image description here

iOS: enter image description here

0
{
  shadowColor: '#d8d8d8',
  shadowRadius: 10,
  elevation: 1,
  backgroundColor: 'Color code'
}

You can set height and width as well on the View style.

ggorlen
  • 44,755
  • 7
  • 76
  • 106
0
import React from "react";
import { View, StyleSheet } from "react-native";

const ViewShadow = ({ children }) => {
    return (
        <View style={styles.container}>
            <View style={styles.box}>{children}</View>
        </View>
    );
};

const styles = StyleSheet.create({
    container: {
        flex: 1,
        justifyContent: "center",
        alignItems: "center",
    },
    box: {
        width: 200,
        height: 200,
        backgroundColor: "fff",
        // Android
        elevation: 8,
        // shadow color
        shadowColor: "blue",
        //iOS
        shadowOffset: { width: 5, height: 5 },
        shadowOpacity: 0.26,
    },
});

export default ViewShadow;

Zahir Masoodi
  • 546
  • 7
  • 23
0

To be able to work with both mobile OS's and web I did the following:

import { Platform } from 'react-native';

   ...Platform.select({
      ios: {
        shadowOpacity: 0.3,
        shadowRadius: 3,
        shadowOffset: {
          height: 0,
          width: 0,
        },
        android: {
          elevation: 1,
        },
        web: {
          boxShadow: '2px 2px 2px 1px rgba(0, 0, 0, 0.2)',
        },
      },
    }),
Ian
  • 1,746
  • 1
  • 15
  • 28