By Aditya Vaidyam

2011-01-21 00:58:32 8 Comments

I want a custom UIView... : I just wanted a blank white view with rounded corners and a light drop shadow (with no lighting effect). I can do each of those one by one but the usual clipToBounds/maskToBounds conflicts occur.


@Dhaval H. Nena 2019-09-25 05:23:27

Here is the solution that will work for sure!

I have created UIView extension with required edges to apply shadow on as below

enum AIEdge:Int {

extension UIView {

    func applyShadowWithCornerRadius(color:UIColor, opacity:Float, radius: CGFloat, edge:AIEdge, shadowSpace:CGFloat)    {

        var sizeOffset:CGSize =

        switch edge {
        case .Top:
            sizeOffset = CGSize(width: 0, height: -shadowSpace)
        case .Left:
            sizeOffset = CGSize(width: -shadowSpace, height: 0)
        case .Bottom:
            sizeOffset = CGSize(width: 0, height: shadowSpace)
        case .Right:
            sizeOffset = CGSize(width: shadowSpace, height: 0)

        case .Top_Left:
            sizeOffset = CGSize(width: -shadowSpace, height: -shadowSpace)
        case .Top_Right:
            sizeOffset = CGSize(width: shadowSpace, height: -shadowSpace)
        case .Bottom_Left:
            sizeOffset = CGSize(width: -shadowSpace, height: shadowSpace)
        case .Bottom_Right:
            sizeOffset = CGSize(width: shadowSpace, height: shadowSpace)

        case .All:
            sizeOffset = CGSize(width: 0, height: 0)
        case .None:
            sizeOffset =

        self.layer.cornerRadius = self.frame.size.height / 2
        self.layer.masksToBounds = true;

        self.layer.shadowColor = color.cgColor
        self.layer.shadowOpacity = opacity
        self.layer.shadowOffset = sizeOffset
        self.layer.shadowRadius = radius
        self.layer.masksToBounds = false

        self.layer.shadowPath = UIBezierPath(roundedRect:self.bounds, cornerRadius:self.layer.cornerRadius).cgPath

Finally, you can call the shadow function as below for any of your UIView subclass, you can also specify the edge to apply shadow on, try different variations as per your need changing parameters of below method call.

viewRoundedToBeShadowedAsWell.applyShadowWithCornerRadius(color: .gray, opacity: 1, radius: 15, edge: AIEdge.All, shadowSpace: 15)

Result image

enter image description here enter image description here enter image description here

Happy coding!

@Sai kumar Reddy 2019-09-19 04:45:39

import UIKit

extension UIView {

    func addShadow(shadowColor: UIColor, offSet: CGSize, opacity: Float, shadowRadius: CGFloat, cornerRadius: CGFloat, corners: UIRectCorner, fillColor: UIColor = .white) {

        let shadowLayer = CAShapeLayer()
        let size = CGSize(width: cornerRadius, height: cornerRadius)
        let cgPath = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: corners, cornerRadii: size).cgPath //1
        shadowLayer.path = cgPath //2
        shadowLayer.fillColor = fillColor.cgColor //3
        shadowLayer.shadowColor = shadowColor.cgColor //4
        shadowLayer.shadowPath = cgPath
        shadowLayer.shadowOffset = offSet //5
        shadowLayer.shadowOpacity = opacity
        shadowLayer.shadowRadius = shadowRadius

@Sergey Grischyov 2017-04-08 15:10:00

Simple Swift 4 solution based on Ade's answer without any additional subviews, subclassing or extra fiddling:

extension UIView {

    func addShadow(offset: CGSize, color: UIColor, radius: CGFloat, opacity: Float) {
        layer.masksToBounds = false
        layer.shadowOffset = offset
        layer.shadowColor = color.cgColor
        layer.shadowRadius = radius
        layer.shadowOpacity = opacity

        let backgroundCGColor = backgroundColor?.cgColor
        backgroundColor = nil
        layer.backgroundColor =  backgroundCGColor

Note that you should set up your view with corner radius and other properties before calling addShadow.

The call this directly from viewDidLoad like this:

btnBottom.addShadow(offset: CGSize.init(width: 0, height: 3), color:, radius: 2.0, opacity: 0.35)

Final result:


Super easy and simple!

EDIT: I see a lot of people having some issues with this example, so I created a simple Xcode project to illustrate how it should be used.

@Parth Dabhi 2017-05-11 06:47:28

it's not working with we apply corner radius.

@t1ser 2017-06-19 09:27:55

Works OK as described even with cornerRadius.

@Cesare 2017-06-22 17:26:49

Does this work on buttons? Because it's not working on my end.

@Hemang 2017-08-31 08:56:11

This isn't working. I guess @SergeyGrischyov, has used a corner radius background image for this button.

@Hemang 2017-08-31 10:27:51

I tried following the exact steps you suggested. But still no luck. It would be great if you share a sample (on Github) to see how you have done which seems impossible for me and other people.

@trupin 2017-09-07 20:58:13

Managed to make it work only by removing this line layer.shadowPath = UIBezierPath.init(roundedRect: layer.bounds, cornerRadius: layer.cornerRadius).cgPath. Can't explain why though, does someone has an explanation for that?

@Curnelious 2018-11-03 10:02:46

doesn't work at all, the corner radius will be ruin

@Sergey Grischyov 2018-11-15 11:07:54

@Curnelious feel free to take a look at the updated answer with an Xcode project example. It cannot not work :)

@Krishnarjun Banoth 2019-03-07 07:14:28

This one worked perfectly for me.

@Rishabh 2019-09-04 04:23:51

This worked for me too, just need to one thing more is to make all the subviews background-color to clear so that only container view has a visible background and this resolved my problem. Thanks!! @SergeyGrischyov

@jeevan eashwar 2018-08-30 15:01:48

extension UIView {
    func dropRoundedShadowForAllSides() {
        let backgroundView = UIView(frame:self.frame)
        let radius = frame.height/2
        backgroundView.layer.masksToBounds = false
        self.layer.masksToBounds = true
        backgroundView.layer.shadowOffset = CGSize(width: 0.0, height: 0.0)
        backgroundView.layer.shadowRadius = 4
        backgroundView.layer.shadowOpacity = 0.4

        let path = UIBezierPath()

        // Start at the Top Left Corner + radius distance
        path.move(to: CGPoint(x: 2*radius, y: 0.0))

        // Move to the Top Right Corner - radius distance
        path.addLine(to: CGPoint(x: backgroundView.frame.size.width - radius, y: 0.0))

        // Move to top right corner + radius down as curve
        let centerPoint1 = CGPoint(x:backgroundView.frame.size.width - radius,y:radius)
        path.addArc(withCenter: centerPoint1, radius: radius, startAngle: 3*(.pi/2), endAngle: 0, clockwise: true)

        // Move to the Bottom Right Corner - radius
        path.addLine(to: CGPoint(x: backgroundView.frame.size.width, y: backgroundView.frame.size.height - radius))

        // Move to top right corner + radius left as curve
        let centerPoint2 = CGPoint(x:backgroundView.frame.size.width - radius,y:backgroundView.frame.size.height - radius)
        path.addArc(withCenter: centerPoint2, radius: radius, startAngle: 0, endAngle: .pi/2, clockwise: true)

        // Move to the Bottom Left Corner - radius
        path.addLine(to: CGPoint(x: radius, y: backgroundView.frame.size.height))

        // Move to left right corner - radius up as curve
        let centerPoint3 = CGPoint(x:radius,y:backgroundView.frame.size.height - radius)
        path.addArc(withCenter: centerPoint3, radius: radius, startAngle: .pi/2, endAngle: .pi, clockwise: true)

        // Move to the top Left Corner - radius
        path.addLine(to: CGPoint(x: 0, y: radius))

        // Move to top right corner + radius down as curve
        let centerPoint4 = CGPoint(x:radius,y:radius)
        path.addArc(withCenter: centerPoint4, radius: radius, startAngle: .pi, endAngle: 3 * (.pi/2), clockwise: true)


        backgroundView.layer.shadowPath = path.cgPath
        if let superView = self.superview {
            superView.sendSubview(toBack: backgroundView)
            superView.bringSubview(toFront: self)


@Baptiste Mille-Mathias 2018-08-30 15:21:32

Hi, thanks for your answer, you should add some comments to your code to explain a bit as described in How to Answer.

@onmyway133 2017-04-24 12:53:29

You need to use use shadowView and roundView

enter image description here


  • Must has background color
  • Should lay behind roundView
  • The trick is to layout shadowView a bit inside, and its shadow needs to glow out. Adjust the insets so that shadowView is completely invisible behind roundView


  • Must clips subviews

The code

addSubviews(shadowView, roundView)
roundView.addSubviews(titleLabel, subtitleLabel, imageView)

// need inset
shadowView.pinEdges(view: self, inset: UIEdgeInsets(constraintInsets: 2))
roundView.pinEdges(view: self)

do {
  shadowView.backgroundColor = .white // need background
  let layer = shadowView.layer
  layer.shadowColor =
  layer.shadowRadius = 3
  layer.shadowOffset = CGSize(width: 3, height: 3)
  layer.shadowOpacity = 0.7
  layer.shouldRasterize = true

do {
  roundView.backgroundColor = .white
  let layer = roundView.layer
  layer.masksToBounds = true
  layer.cornerRadius = 5

Or you can just do below without specifying clipToBounds/maskToBounds

layer.shadowColor = UIColor.gray.cgColor
layer.shadowOffset = CGSize(width: 3, height: 3)
layer.shadowOpacity = 0.8

@rbaldwin 2018-05-01 20:46:11

Using Swift 4 and Xcode 9, this is a working example of rounding an ImageView with a drop shadow, and a border.

    //set dimensions and position of image (in this case, centered)
    let imageHeight: CGFloat = 150, imageWidth: CGFloat = 150
    let xPosition = (self.view.frame.width / 2) - (imageWidth / 2)
    let yPosition = (self.view.frame.height / 2) - (imageHeight / 2)

    //set desired corner radius
    let cornerRadius: CGFloat = 20

    //create container for the image
    let imageContainer = UIView(frame: CGRect(x: xPosition, y: yPosition, width: imageWidth, height: imageHeight))

    //configure the container
    imageContainer.clipsToBounds = false
    imageContainer.layer.shadowColor =
    imageContainer.layer.shadowOpacity = 1
    imageContainer.layer.shadowOffset = CGSize(width: 3.0, height: 3.0)
    imageContainer.layer.shadowRadius = 5
    imageContainer.layer.shadowPath = UIBezierPath(roundedRect: imageContainer.bounds, cornerRadius: cornerRadius).cgPath

    //create imageView
    let imageView = UIImageView(frame: imageContainer.bounds)

    //configure the imageView
    imageView.clipsToBounds = true
    imageView.layer.cornerRadius = cornerRadius
    //add a border (if required)
    imageView.layer.borderColor =
    imageView.layer.borderWidth = 1.0
    //set the image
    imageView.image = UIImage(named: "bird")

    //add the views to the superview

enter image description here

If you want the image to be circular: (and shown without border)

let cornerRadius = imageWidth / 2

enter image description here

@dGambit 2018-03-07 23:08:22

Something swifty tested in swift 4

import UIKit

extension UIView {
    @IBInspectable var dropShadow: Bool {
            if newValue {
                layer.shadowColor =
                layer.shadowOpacity = 0.4
                layer.shadowRadius = 1
                layer.shadowOffset =
            } else {
                layer.shadowColor = UIColor.clear.cgColor
                layer.shadowOpacity = 0
                layer.shadowRadius = 0
                layer.shadowOffset =
        get {
            return layer.shadowOpacity > 0


enter image description here

If you enable it in the Inspector like this:

enter image description here

It will add the User Defined Runtime Attribute, resulting in:

enter image description here

(I added previously the cornerRadius = 8)


@Awais Fayyaz 2018-01-30 12:10:52

Swift 4 Solution for making UICollectionViewCell round and adding Shadows, without any extensions and complications :)

Note: For simple views e.g Buttons. See the @suragch's Answer in this post. Tested successfully for buttons

In case if any one still struggling to round the corners and add shadows at the same time. Although this solution works with UICollectionViewCell, it can be generalized to any view.

This technique worked for me without making any extensions and all the complicated stuff. I am working with storyBoard.


You must add a UIView (lets say it "containerView") inside your UICollectionViewCell in storyBoard and add all the required views (buttons, images etc) inside this containerView. See the Screenshot. Structure of Cell

Connect the outlet for containerView. Add following lines of code in CellforItemAtIndexPath delegate function.

//adds shadow to the layer of cell

cell.layer.cornerRadius = 3.0
    cell.layer.masksToBounds = false
    cell.layer.shadowColor =
    cell.layer.shadowOffset = CGSize(width: 0, height: 0)
    cell.layer.shadowOpacity = 0.6

//makes the cell round 

let containerView = cell.containerView!
    containerView.layer.cornerRadius = 8
    containerView.clipsToBounds = true


See the simulator Screenshot Rounded corners with Shadows (UICollectionViewCell)

@Alex Stone 2013-03-24 02:54:25

I solved the problem using the following trick when assigning shadow path for the container view :

[UIBezierPath bezierPathWithRoundedRect:cell.bounds cornerRadius:12]

Notice that the path given to the shadow is a rounded rectangle with the same corner radius as the background that the cell contains:

//this is the border for the UIView that is added to a cell
cell.backgroundView.layer.cornerRadius = 12;
cell.backgroundView.layer.masksToBounds = YES;
cell.backgroundView.layer.borderColor = [UIColor darkGrayColor].CGColor;
cell.backgroundView.layer.borderWidth = 1;

//this is the shadow around the cell itself (cannot have round corners with borders and shadow, need to use two views
cell.layer.shadowRadius = 2;
cell.layer.cornerRadius = 12;
cell.layer.masksToBounds = NO;
[[cell layer] setShadowColor:[[UIColor darkGrayColor] CGColor]];

[[cell layer] setShadowOffset:CGSizeMake(0.0,0.0)];
[[cell layer] setShadowOpacity:1.0];

UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:cell.bounds cornerRadius:12];
[[cell layer] setShadowPath:[path CGPath]];

@programmer 2017-10-05 15:26:40

Best answer because it explains the right way to add shadow to a rounder cornered view. Thanks @Alex Stone

@Suragch 2016-01-25 02:07:05


enter image description here

// corner radius
blueView.layer.cornerRadius = 10

// border
blueView.layer.borderWidth = 1.0
blueView.layer.borderColor =

// shadow
blueView.layer.shadowColor =
blueView.layer.shadowOffset = CGSize(width: 3, height: 3)
blueView.layer.shadowOpacity = 0.7
blueView.layer.shadowRadius = 4.0

Exploring the options

enter image description here

enter image description here

enter image description here

enter image description here

enter image description here

Problem 1: Shadow gets clipped off

What if there are sublayers or subviews (like an image) whose content we want to clip to the bounds of our view?

enter image description here

We can accomplish this with

blueView.layer.masksToBounds = true

(Alternatively, blueView.clipsToBounds = true gives the same result.)

enter image description here

But, oh no! The shadow was also clipped off because it's outside of the bounds! What to do? What to do?


Use separate views for the shadow and the border. The base view is transparent and has the shadow. The border view clips any other subcontent that it has to its borders.

// add the shadow to the base view
baseView.backgroundColor = UIColor.clear
baseView.layer.shadowColor =
baseView.layer.shadowOffset = CGSize(width: 3, height: 3)
baseView.layer.shadowOpacity = 0.7
baseView.layer.shadowRadius = 4.0

// add the border to subview
let borderView = UIView()
borderView.frame = baseView.bounds
borderView.layer.cornerRadius = 10
borderView.layer.borderColor =
borderView.layer.borderWidth = 1.0
borderView.layer.masksToBounds = true

// add any other subcontent that you want clipped
let otherSubContent = UIImageView()
otherSubContent.image = UIImage(named: "lion")
otherSubContent.frame = borderView.bounds

This gives the following result:

enter image description here

Problem 2: Poor performance

Adding rounded corners and shadows can be a performance hit. You can improve performance by using a predefined path for the shadow and also specifying that it be rasterized. The following code can be added to the example above.

baseView.layer.shadowPath = UIBezierPath(roundedRect: baseView.bounds, cornerRadius: 10).cgPath
baseView.layer.shouldRasterize = true
baseView.layer.rasterizationScale = UIScreen.main.scale

See this post for more details. See here and here also.

This answer was tested with Swift 4 and Xcode 9.

@EI Captain v2.0 2017-04-21 11:58:35

@Suragch so for only border, we need to use separate view or separate views for corner radius and shadow too?

@Suragch 2017-04-21 12:36:57

@EICaptainv2.0, If you only want a border (and/or corner radius) then you don't need a separate view. The separate view is for the situation where you need round corners and shadow.

@Rutger Huijsmans 2017-04-24 06:06:43

This isn't working for me. When I set the back ground color to clear on the baseView a shadow does not appear anymore. What am I doing wrong?

@Aleksander 2017-10-16 23:23:35

Not working, setting baseView.backgroundColor = UIColor.clear removes the shadow. Only if you set a background color will you see it.

@Markus 2017-10-28 21:19:03


@Suragch 2017-12-06 06:37:43

@Markus, I retested the code in my answer and it still worked with Swift 4 and Xcode 9.

@Suragch 2017-12-08 02:51:21

@Aleksander, I retested the code in my answer and it still worked with Swift 4 and Xcode 9. Even with the clear background color on the base view it still worked. I'm not sure why it wasn't working for you.

@Mike Vosseller 2018-01-08 15:00:02

FYI I was initially seeing the same problem that other commenters were seeing where the baseView's shadow not displaying when it's background color was clear. The problem was that I was only running the first part of the code (the baseView stuff). Once I added the borderView as a subview the shadow began displaying. Seems that for the shadow to display there must be at least one visible border (or background) in it's view hierarchy. So be sure to have borderView.layer.borderWidth >= 0 with a non-transparent borderView.layer.borderColor (or a non-transparent background color)

@Satyendra Pandey 2018-01-27 09:37:49

@Suragch, I want to create rounded button with shadow effect so how can i add view in it ? If i am not wrong the click event will not be generated if view is added on button as subview ?

@Martin 2019-04-07 05:34:07

If you are using autolayout, a layoutIfNeeded() might be necessary before drawing the shadow path.

@D. Pratt 2019-07-01 18:04:59

This is one of the best explanations I have come across on SO. Great job, and thank you so much!

@benmore99 2017-12-01 10:52:12

Swift 4 : Create Subclass of UIView

class ShadowView: UIView {

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)

        // corner radius
        self.layer.cornerRadius = 10

        // border
        self.layer.borderWidth = 1.0
        self.layer.borderColor =

        // shadow
        self.layer.shadowColor =
        self.layer.shadowOffset = CGSize(width: 3, height: 3)
        self.layer.shadowOpacity = 0.7
        self.layer.shadowRadius = 4.0



Use Class Shadow View

@Issam eddine bellemallem 2017-09-21 13:27:05

You need add masksToBounds = true for combined between corderRadius shadowRadius.

button.layer.masksToBounds = false;

@Thomás Calmon 2017-05-13 22:18:36

Swift 3 & IBInspectable solution:
Inspired by Ade's solution

First, create an UIView extension:

//  UIView-Extension.swift

import Foundation
import UIKit

extension UIView {
     // Shadow
     @IBInspectable var shadow: Bool {
          get {
               return layer.shadowOpacity > 0.0
          set {
               if newValue == true {

     fileprivate func addShadow(shadowColor: CGColor =, shadowOffset: CGSize = CGSize(width: 3.0, height: 3.0), shadowOpacity: Float = 0.35, shadowRadius: CGFloat = 5.0) {
          let layer = self.layer
          layer.masksToBounds = false

          layer.shadowColor = shadowColor
          layer.shadowOffset = shadowOffset
          layer.shadowRadius = shadowRadius
          layer.shadowOpacity = shadowOpacity
          layer.shadowPath = UIBezierPath(roundedRect: layer.bounds, cornerRadius: layer.cornerRadius).cgPath

          let backgroundColor = self.backgroundColor?.cgColor
          self.backgroundColor = nil
          layer.backgroundColor =  backgroundColor

     // Corner radius
     @IBInspectable var circle: Bool {
          get {
               return layer.cornerRadius == self.bounds.width*0.5
          set {
               if newValue == true {
                    self.cornerRadius = self.bounds.width*0.5

     @IBInspectable var cornerRadius: CGFloat {
          get {
               return self.layer.cornerRadius

          set {
               self.layer.cornerRadius = newValue

     // Borders
     // Border width
     public var borderWidth: CGFloat {
          set {
               layer.borderWidth = newValue

          get {
               return layer.borderWidth

     // Border color
     public var borderColor: UIColor? {
          set {
               layer.borderColor = newValue?.cgColor

          get {
               if let borderColor = layer.borderColor {
                    return UIColor(cgColor: borderColor)
               return nil

Then, simply select your UIView in interface builder setting shadow ON and corner radius, like below:

Selecting your UIView

Setting shadow ON & corner radius

The result!


@inexcitus 2018-06-17 17:58:53

Like every other "solution" in this thread, it simply doesn't work, at least not on iOS 11.0 / Swift 4.1.

@Thomás Calmon 2018-10-20 13:11:08

Did you read "Swift 3" in the begin of the thread? So, it means that is a Swift 3 solution, I didn't test it in Swift 4.1 because I don't need it anymore. Feel free to edit the answer and give a solution. ;) Cheers

@Liu Chao 2017-04-11 09:17:58

I write this UIView category method to solve this problem, uses separate views for the shadow and the corner radius.

-(UIView *)shadowedWrapViewWithBounds:(CGRect)bounds {
UIView *baseView = [[UIView alloc] init];
baseView.bounds = bounds;
baseView.backgroundColor = [UIColor clearColor];
baseView.layer.shadowColor = [UIColor blackColor].CGColor;
baseView.layer.shadowOffset = CGSizeMake(0, 0);
baseView.layer.shadowOpacity = 0.7;
baseView.layer.shadowRadius = 4.0;

// improve performance
baseView.layer.shadowPath = [UIBezierPath bezierPathWithRoundedRect:baseView.bounds cornerRadius:4].CGPath;
baseView.layer.shouldRasterize = YES;
baseView.layer.rasterizationScale = [UIScreen mainScreen].scale;

[baseView addSubview:self];
//use Masonry autolayout, self can set corner radius
[self makeConstraints:^(MASConstraintMaker *make) {

return baseView;

@Mahesh Agrawal 2016-12-29 13:22:35

I have tried so many solutions from this post and ended up with the below solution. This is full proof solution unless you need to drop shadow on a clear color view.

- (void)addShadowWithRadius:(CGFloat)shadowRadius withOpacity:(CGFloat)shadowOpacity withOffset:(CGSize)shadowOffset withColor:(UIColor *)shadowColor withCornerradius:(CGFloat)cornerRadius
    UIView *viewShadow = [[UIView alloc]initWithFrame:self.frame];
    viewShadow.backgroundColor = [UIColor whiteColor];
    viewShadow.layer.shadowColor = shadowColor.CGColor;
    viewShadow.layer.shadowOffset = shadowOffset;
    viewShadow.layer.shadowRadius = shadowRadius;
    viewShadow.layer.shadowOpacity = shadowOpacity;
    viewShadow.layer.cornerRadius = cornerRadius;
    viewShadow.layer.masksToBounds = NO;
    [self.superview insertSubview:viewShadow belowSubview:self];

    [viewShadow setTranslatesAutoresizingMaskIntoConstraints:NO];
    [self.superview addConstraint:[NSLayoutConstraint constraintWithItem:viewShadow attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeWidth multiplier:1.0 constant:0]];
    [self.superview addConstraint:[NSLayoutConstraint constraintWithItem:viewShadow attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeHeight multiplier:1.0 constant:0]];
    [self.superview addConstraint:[NSLayoutConstraint constraintWithItem:viewShadow attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:viewShadow attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:0]];
    [self.superview addConstraint:[NSLayoutConstraint constraintWithItem:viewShadow attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:viewShadow attribute:NSLayoutAttributeCenterY multiplier:1.0 constant:0]];
    [self layoutIfNeeded];

    self.layer.cornerRadius = cornerRadius;
    self.layer.masksToBounds = YES;

@Ben Thomas 2018-04-10 21:29:08

The expression is "fool proof". :)

@Ben Thomas 2018-04-12 22:54:01

I was just correcting the English. :) The solution works.

@Yung Dai 2016-12-22 17:14:38

Here is my version in Swift 3 for a UIView

let corners:UIRectCorner = [.bottomLeft, .topRight]
let path = UIBezierPath(roundedRect: rect, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
let mask = CAShapeLayer()

mask.path = path.cgPath
mask.fillColor = UIColor.white.cgColor

let shadowLayer = CAShapeLayer()
shadowLayer.shadowColor =
shadowLayer.shadowOffset = CGSize(width: 0.0, height: 4.0)
shadowLayer.shadowRadius = 6.0
shadowLayer.shadowOpacity = 0.25
shadowLayer.shadowPath = mask.path

self.layer.insertSublayer(shadowLayer, at: 0)
self.layer.insertSublayer(mask, at: 1)

@Mehul Parmar 2016-02-01 04:40:52

The following worked best for me (this code lies in UIView extension, so self denotes some UIView to which we must add a shadow and round corner)

- (void)addShadowViewWithCornerRadius:(CGFloat)radius {

UIView *container = self.superview;

if (!container) {

UIView *shadowView = [[UIView alloc] init];
shadowView.translatesAutoresizingMaskIntoConstraints = NO;
shadowView.backgroundColor = [UIColor lightGrayColor];
shadowView.layer.cornerRadius = radius;
shadowView.layer.masksToBounds = YES;

[container addSubview:shadowView];
[container bringSubviewToFront:shadowView];

[container addConstraint:[NSLayoutConstraint constraintWithItem:shadowView
[container addConstraint:[NSLayoutConstraint constraintWithItem:shadowView

[container addConstraint:[NSLayoutConstraint constraintWithItem:shadowView
[container addConstraint:[NSLayoutConstraint constraintWithItem:shadowView
[container sendSubviewToBack:shadowView];

The main difference between this and other code samples is that this adds the shadow view as a sibling view (as against adding the current view as subview of shadow view), thereby eliminating the need to modify the existing view hierarchy in any way.

@David C. 2011-08-04 22:15:42

One way to do this is to put the view with rounded corners in a view with the drop shadow.

UIView* roundedView = [[UIView alloc] initWithFrame: frame];
roundedView.layer.cornerRadius = 5.0;
roundedView.layer.masksToBounds = YES;

UIView* shadowView = [[UIView alloc] initWithFrame: frame];
shadowView.layer.shadowColor = [UIColor blackColor].CGColor;
shadowView.layer.shadowRadius = 5.0;
shadowView.layer.shadowOffset = CGSizeMake(3.0, 3.0);
shadowView.layer.shadowOpacity = 1.0;
[shadowView addSubview: roundedView];

Then you can add the shadowView wherever you want.

@Deepak G M 2013-02-15 06:50:43

Amit, you have to set maskToBounds/clipToBounds = YES for the * roundedView only *. DO NOT set this to the shadowView. I have not tried the above code but know for sure that this solution definitely works though not ideal. The higher shadowRadius takes care of the corner radius areas. Set the shadowRadius to 0 or 1 and you will notice what I am trying to say.

@Bo. 2013-03-17 18:25:31

Something like shadowView.layer.shadowOpacity = 0.6; is missing

@Chris 2014-09-04 04:55:03

"shadowView.layer.opacity = 1.0" should be "shadowView.layer.shadowOpacity = 1.0"

@Mansurov Ruslan 2015-10-19 16:13:23

Works on iOS 9 if use shadowView.layer.shadowOpacity = 1.0

@Softlion 2015-12-03 13:19:33

Code fixed for shadowOpacity

@daniel.gindi 2012-10-19 07:51:49

If you are struggling because of the rounded corners vs. subviews vs. masksToBounds, then try using my function:

- (UIView*)putView:(UIView*)view insideShadowWithColor:(UIColor*)color andRadius:(CGFloat)shadowRadius andOffset:(CGSize)shadowOffset andOpacity:(CGFloat)shadowOpacity
    CGRect shadowFrame; // Modify this if needed
    shadowFrame.size.width = 0.f;
    shadowFrame.size.height = 0.f;
    shadowFrame.origin.x = 0.f;
    shadowFrame.origin.y = 0.f;
    UIView * shadow = [[UIView alloc] initWithFrame:shadowFrame];
    shadow.userInteractionEnabled = NO; // Modify this if needed
    shadow.layer.shadowColor = color.CGColor;
    shadow.layer.shadowOffset = shadowOffset;
    shadow.layer.shadowRadius = shadowRadius;
    shadow.layer.masksToBounds = NO;
    shadow.clipsToBounds = NO;
    shadow.layer.shadowOpacity = shadowOpacity;
    [view.superview insertSubview:shadow belowSubview:view];
    [shadow addSubview:view];
    return shadow;

call it on your view. whether your view has rounded corners, no matter its size, its shape - a nice shadow will be drawn.

Just keep the return value of the function so you can refer to it when you want to remove the table (or for example use insertSubview:aboveView:)

@manujmv 2013-05-06 10:03:20

it works fine. But if view has gesture recognizers, then it will not work. how can we solve it?

@daniel.gindi 2013-05-06 11:45:20

@manujmv Do you see the lines where "// Modify this if needed" is specified? That's what you need. shadow.userInteractionEnabled = YES;

@daniel.gindi 2013-05-06 15:38:09

@manujmv then you should test the frames of the view and subview to see why. something probably is not right there. this exact code works for me in some very nice apps

@Chris Hart 2013-05-11 22:17:56

This solution works great for UITableViews with rounded corners. Wish I could give it more up votes. Thanks!

@Carlos López 2014-08-28 03:38:28

doesn't work with buttons. They can't be clicked after this

@daniel.gindi 2014-08-28 06:52:58

@CarlosEduardoLópez Do you see the shadow.userInteractionEnabled = NO; // Modify this if needed line? So this is the case where needed. userInteractionEnabled is a basic and popular property you should be already familiar with :-)

@Carlos López 2014-08-28 14:55:07

I'm familiar with that, but that's not the problem. The problem is the CGRect position. If you change the background, you will notice the views are in the top corner, so you can enable the interaction, but they won't pass the gestures cause they're not in the same position

@daniel.gindi 2014-08-28 18:06:54

Gestures are usually working fine with this, at least for me. You situation is probably different in an important manner

@manish_kumar 2015-08-21 08:44:47

@daniel.gindi The solution works great..!!

@Max Hanzo Ueda 2016-04-19 19:06:50

Basically, I didn't pay attention to the comment in the line where CGRect shadowFrame is declared, that's why this solution didn't work with UIButton & UITableView. I just did shadowFrame = view.frame and erased those lines: shadowFrame.size.width = 0.f; shadowFrame.size.height = 0.f; shadowFrame.origin.x = 0.f; shadowFrame.origin.y = 0.f; Carlos Eduardo López solved and answered here:…

@Evan Mulawski 2011-01-21 01:04:24

The following code snippet adds a border, border radius, and drop shadow to v, a UIView:

// border radius
[v.layer setCornerRadius:30.0f];

// border
[v.layer setBorderColor:[UIColor lightGrayColor].CGColor];
[v.layer setBorderWidth:1.5f];

// drop shadow
[v.layer setShadowColor:[UIColor blackColor].CGColor];
[v.layer setShadowOpacity:0.8];
[v.layer setShadowRadius:3.0];
[v.layer setShadowOffset:CGSizeMake(2.0, 2.0)];

You can adjust the settings to suit your needs.

Also, add the QuartzCore framework to your project and:

#import <QuartzCore/QuartzCore.h>

See my other answer regarding masksToBounds.


This may not work in all cases. If you find that this method interferes with other drawing operations that you are performing, please see this answer.

@Aditya Vaidyam 2011-01-21 02:37:34

Well the problem with it is that when I set corner radius, it sets maskToBounds: YES, whereas the shadow requires clipToBounds: NO (where clipToBounds does the same as maskToBounds)

@hfossli 2011-03-23 10:35:38

same problem here. If I have a background color I want that to be clipped to the rounded corners. To do that I have to use maskToBounds=TRUE, but then the shadow dissapears..

@SilithCrowe 2012-01-27 21:55:47

For newbies like me: I had to import the QuartzCore framework into my project in order to call methods on the layer object.

@lindon fox 2012-07-25 02:40:05

Note for people concerned with performance: This is not a fast operation. If you wanted to add a drop shadow to a button in every row of a table view for example, it would have the potential to cause some sluggish transitions and scrolling. Pre-rendering the shadow as an image and using that would be much more efficient.

@Pascal 2012-11-30 19:37:38

As several have pointed out, this doesn't work. Just set the view's background color to red and a corner radius greater than 2.f and you'll see.

@Kalle 2013-01-02 12:18:39

It does work, but it has limitations. For example if you have another UIView near either of the corners, it will cover the rounding unless it's transparent. I just solved this in a very crude way by adding rounded corners to the inner view and putting a cover over its other edge to get the effect. Not ideal. Wish Apple would fix.

@Pascal 2013-07-19 16:32:09

@Kalle That's why I said it doesn't work if you e.g. have a red background color for the view. It's a hack that works for some if not most use cases, but it's not the right answer technically.

@Suran 2013-11-28 08:30:00

Hi, this is working for me, if I'm creating a UIView through code(obviously masksToBounds is false). But, when I'm trying to use the above code on a UIView that is created from nib, only one works at a time. ie, shadow and corner radius doesn't work together. Please help

@Kpmurphy91 2013-12-09 19:10:34

The way to get this to work the right way is to use an inner container view, which will house your border and your background color, both with a corner radius. This view will be clipped to bounds! The second, outer container view will house the first one, has the same frame, with just a drop shadow. I've done this quite a few times to combine a border, drop shadow, and corner radius. It's really annoying, but it works really well.

@Yarneo 2014-05-27 18:48:40

Doesn't work. No idea why there are so many up votes. Was this applicable in older versions?

@Yarneo 2014-05-28 18:09:37

@EvanMulawski Im using 7.1. The maskToBounds when its off makes the rounded corner not applicable, and when its on, theres no shadow, as its outside the view.

@Yarneo 2015-02-14 01:44:34

@EvanMulawski, if you do maskToBounds as true, you will be stopping any kind of drop shadow to clip outside of the view's bounds. So I don't understand how you got a successful effect.

@c.dunlap 2016-04-14 19:21:49

This doesn't work. The only way to do what the OP is asking is to use two views as @Kpmurphy91 stated.

@Mehdico 2018-12-02 19:04:03

Wrong Answer. border was drawn but corners not not mask.

@Travis Delly 2019-03-29 00:18:50

Why does this work? it definitely worked for me, but i thought that if you add a shadow, the corners won't respect the cornerRadius.... Is it becuase of the quartzcore of someting?

@S. Koshelnyk 2019-04-10 23:16:19

Worked for me in Xamarin.iOS. Thanks a lot! I also made borderRadius = 200 so I have nice tint around my view

@Albert Renshaw 2019-07-26 21:48:19

for those wondering, you have to declare the corner radius FIRST then you can declare the shadow and they both work together, if you do it the other way around the corner radius code ends up clipping the shadow. It seems like the order would not matter, I too was surprised when it did indeed work when setting the corners first.

@lwz7512 2015-05-29 14:30:16

After one whole day research of the round corner view with shadow, I'm glad to post my custom uiview class here, hope to end this question:


#import <UIKit/UIKit.h>

@interface RoundCornerShadowView : UIView



#import "RoundCornerShadowView.h"

@implementation RoundCornerShadowView

// *** must override this method, not the other method ***
// otherwise, the background corner doesn't disappear....
// @2015/05/29
-(void) layoutSubviews {
    [super layoutSubviews];//is must to ensure rightly layout children view

    //1. first, create Inner layer with content
    CALayer *innerView = [CALayer layer];
    innerView.frame = CGRectMake(0,0,self.bounds.size.width,self.bounds.size.height);
    //instead of: innerView.frame = self.frame;
    innerView.borderWidth = 1.0f;
    innerView.cornerRadius = 6.0f;
    innerView.masksToBounds = YES;
    innerView.borderColor = [[UIColor lightGrayColor] CGColor];
    innerView.backgroundColor = [[UIColor whiteColor] CGColor];
    //put the layer to the BOTTOM of layers is also a MUST step...
    //otherwise this layer will overlay the sub uiviews in current uiview...
    [self.layer insertSublayer:innerView atIndex:0];

    //2. then, create shadow with self layer
    self.layer.masksToBounds = NO;
    self.layer.shadowColor = [[UIColor darkGrayColor] CGColor];
    self.layer.shadowOpacity = 0.4f;
    //shadow length
    self.layer.shadowRadius = 2.0f;
    //no offset
    self.layer.shadowOffset = CGSizeMake(0, 0);
    //right down shadow
    //[self.layer setShadowOffset: CGSizeMake(1.0f, 1.0f)];

    //3. last but important, MUST clear current view background color, or the color will show in the corner!
    self.backgroundColor = [UIColor clearColor];


so, NO need to add subview in view or below in target view, just add one layer in current view, and do 3 step to complete it!

take a close look at to the comments in the code, it's helpful to understanding the component!

@Darshit Shah 2015-05-20 05:36:30

Shadow + Border + Corner Radius enter image description here

    scrollview.backgroundColor = [UIColor whiteColor]; 
    CALayer *ScrlViewLayer = [scrollview layer];
    [ScrlViewLayer setMasksToBounds:NO ];
    [ScrlViewLayer setShadowColor:[[UIColor lightGrayColor] CGColor]];
    [ScrlViewLayer setShadowOpacity:1.0 ];
    [ScrlViewLayer setShadowRadius:6.0 ];
    [ScrlViewLayer setShadowOffset:CGSizeMake( 0 , 0 )];
    [ScrlViewLayer setShouldRasterize:YES];
    [ScrlViewLayer setCornerRadius:5.0];
    [ScrlViewLayer setBorderColor:[UIColor lightGrayColor].CGColor];
    [ScrlViewLayer setBorderWidth:1.0];
    [ScrlViewLayer setShadowPath:[UIBezierPath bezierPathWithRect:scrollview.bounds].CGPath];

@Ford Davis 2015-04-23 05:20:51

This is how you do it, with rounded corners and rounded shadows without bothering with paths.

//Inner view with content
[imageView.layer setBorderColor:[[UIColor lightGrayColor] CGColor]];
[imageView.layer setBorderWidth:1.0f];
[imageView.layer setCornerRadius:8.0f];
[imageView.layer setMasksToBounds:YES];

//Outer view with shadow
UIView* shadowContainer = [[UIView alloc] initWithFrame:imageView.frame];
[shadowContainer.layer setMasksToBounds:NO];
[shadowContainer.layer setShadowColor:[[UIColor blackColor] CGColor]];
[shadowContainer.layer setShadowOpacity:0.6f];
[shadowContainer.layer setShadowRadius:2.0f];
[shadowContainer.layer setShadowOffset: CGSizeMake(0.0f, 2.0f)];

[shadowContainer addSubview:imageView];

The view with content, in my case a UIImageView, has a corner radius and therefore has to mask to bounds.

We create another equally sized view for the shadows, set it's maskToBounds to NO and then add the content view to the container view (e.g. shadowContainer).

@Vaibhav Saran 2015-04-08 06:29:24

You need to use two UIViews to achieve this. One UIView will work like shadow and other one will work for rounded border.

Here is a code snippet a Class Method with a help of a protocol:

@implementation UIMethods

+ (UIView *)genComposeButton:(UIViewController <UIComposeButtonDelegate> *)observer;
    UIView *shadow = [[UIView alloc]init];
    shadow.layer.cornerRadius = 5.0;
    shadow.layer.shadowColor = [[UIColor blackColor] CGColor];
    shadow.layer.shadowOpacity = 1.0;
    shadow.layer.shadowRadius = 10.0;
    shadow.layer.shadowOffset = CGSizeMake(0.0f, -0.5f);

    UIButton *btnCompose = [[UIButton alloc]initWithFrame:CGRectMake(0, 0,60, 60)];
    [btnCompose setUserInteractionEnabled:YES];
    btnCompose.layer.cornerRadius = 30;
    btnCompose.layer.masksToBounds = YES;
    [btnCompose setImage:[UIImage imageNamed:@"60x60"] forState:UIControlStateNormal];
    [btnCompose addTarget:observer action:@selector(btnCompose_click:) forControlEvents:UIControlEventTouchUpInside];
    [shadow addSubview:btnCompose];
    return shadow;

In the code above btnCompose_click: will become a @required delegate method which will fire on the button click.

And here I added a button to my UIViewController like this:

UIView *btnCompose = [UIMethods genComposeButton:self];
btnCompose.frame = CGRectMake(self.view.frame.size.width - 75,
                          self.view.frame.size.height - 75,
                          60, 60);
[self.view addSubview:btnCompose];

The result will look like this:

enter image description here

@Shaopeng Wang 2015-02-10 10:20:32

Here is the solution for masksToBounds conflict problem, it works for me.

After you set the corderRadius/borderColor/shadow and so on, set masksToBounds as NO:

v.layer.masksToBounds = NO;

@MontDeska 2016-04-18 23:57:57

This worked for me!! omg I almost did all the tricks above you answer! thanks Shaopeng.

@Ade 2014-09-05 20:24:26

This worked for me. Trick was to move the background color from the main view to the layer.

CALayer *layer = view.layer;
layer.cornerRadius = 15.0f;
layer.masksToBounds = NO;

layer.shadowOffset = CGSizeMake(0, 3);
layer.shadowColor = [[UIColor blackColor] CGColor];
layer.shadowRadius = 2.0f;
layer.shadowOpacity = 0.35f;
layer.shadowPath = [[UIBezierPath bezierPathWithRoundedRect:layer.bounds cornerRadius:layer.cornerRadius] CGPath];

CGColorRef  bColor = view.backgroundColor.CGColor;
view.backgroundColor = nil;
layer.backgroundColor =  bColor ;

@trapper 2015-10-31 00:46:10

This is the best solution

@emem 2016-10-16 15:09:37

Although all the other solutions work, and perhaps they are more general, this is by far the best solution to the problem. Adding subviews or sublayers create a world or pain trying to maintain the frame sizes, or, at best, may cause performance issues.

@Axy 2016-12-06 03:54:56

This should be the answer. Clean and elegant.

@Roberto Ferraz 2016-12-20 09:09:40

Best solution and definitely elegant!

@Womble 2017-02-27 02:43:51

Wow, this actually works. I don't understand why it should work -- you'd think the view's backgroundColor properly would directly map to the layer.backgroundColor property on iOS -- but it DOES WORK. (Xcode 8, Swift 3.) Well done, and thanks. This should be the accepted answer.

@Sergey Grischyov 2017-04-08 15:11:30

I've created a Swift 3.1 version of your answer using UIView extension here - thanks for the inspiration!

@Thomás Calmon 2017-05-13 22:20:43

You inspired me, I finally got It working! Thanks you. I did an extension to integrate IBInspectable your solution.

@trupin 2017-09-07 21:07:01

The only way I found which works for me is to remove this line layer.shadowPath = [[UIBezierPath bezierPathWithRoundedRect:layer.bounds cornerRadius:layer.cornerRadius] CGPath];. Any idea why?

@e.dimitrow 2017-11-04 09:31:47

Thanks, best solution

@umakanta 2018-01-31 09:10:24

if UIView is having subViews extreme at the margin, it fails.

@Jeff 2018-07-30 04:10:59

Genius! Thank you!

@Andrew Kinnie 2018-11-14 05:30:58

Not sure why, but it is not working for me. Turning off clips to bounds prevents the corner radius from working in a filled UIButton. (i.e. not a border, a fill). The shadows work, but the corners do not.

@Carlos López 2014-08-28 15:00:35

I make some changes to the code of daniel.gindi

This is all you need to make it work.

+ (void)putView:(UIView*)view insideShadowWithColor:(UIColor*)color andBlur:         (CGFloat)blur andOffset:(CGSize)shadowOffset andOpacity:(CGFloat)shadowOpacity
    CGRect shadowFrame = view.frame;
    UIView * shadow = [[UIView alloc] initWithFrame:shadowFrame];
    shadow.backgroundColor = [UIColor redColor];
    shadow.userInteractionEnabled = YES; // Modify this if needed
    shadow.layer.shadowColor = color.CGColor;
    shadow.layer.shadowOffset = shadowOffset;
    shadow.layer.shadowRadius = blur;
    shadow.layer.cornerRadius = view.layer.cornerRadius;
    shadow.layer.masksToBounds = NO;
    shadow.clipsToBounds = NO;
    shadow.layer.shadowOpacity = shadowOpacity;
    [view.superview insertSubview:shadow belowSubview:view];

@Digitrance 2014-04-29 13:06:35

daniel.gindi's answer above did the trick for me! (+1 daniel) However, I had to make minor adjustments - change the shadowFrame size to be same as view's frame size, and enable user interaction. Here's the updated code:

+ (UIView*)putView:(UIView*)view insideShadowWithColor:(UIColor*)color andRadius:(CGFloat)shadowRadius andOffset:(CGSize)shadowOffset andOpacity:(CGFloat)shadowOpacity
    CGRect shadowFrame; // Modify this if needed

    // Modified this line
    shadowFrame.size = CGSizeMake(view.frame.size.width, view.frame.size.height);

    shadowFrame.origin.x = 0.f;
    shadowFrame.origin.y = 0.f;
    UIView * shadow = [[UIView alloc] initWithFrame:shadowFrame];

    // Modified this line
    shadow.userInteractionEnabled = YES;
    shadow.layer.shadowColor = color.CGColor;
    shadow.layer.shadowOffset = shadowOffset;
    shadow.layer.shadowRadius = shadowRadius;
    shadow.layer.masksToBounds = NO;
    shadow.clipsToBounds = NO;
    shadow.layer.shadowOpacity = shadowOpacity;

    [shadow addSubview:view];
    return shadow;

I would like to add that in my case, I was trying to add this to a 3rd party view controller, i.e. I did not have direct control over the code. So, here's how I used the function above:

UIView *shadow = [self putView:vc.view 
         insideShadowWithColor:[UIColor blackColor]
                     andOffset:CGSizeMake(0.0, 0.0) 
vc.view = shadow;
vc.view.layer.cornerRadius = 5.0;
vc.view.layer.masksToBounds = YES;

@Abdur Rahman 2013-11-22 11:41:54

The answer provided by Evan Mulawski will work perfectly. The catch is that you have to set the background color for the view to clearColor and the masksToBounds property to NO.

You can set whatever color you want for the view, set it like

v.layer.backgroundColor = your color;

Hope this helps..

@NickBln 2013-10-12 12:39:31

Old thread still current...

I've edited Daniel Gindi's method to make it possible to use it with buttons etc. as well. If anyone needs rounded corners or wants to combine round corners and a border it has to be set on the view's layer which is passed to this method. I've also set the rasterization to speed it up a little.

+ (UIView*)putView:(UIView*)view insideShadowWithColor:(CGColorRef)color 
    // Must have same position like "view"
    UIView *shadow = [[UIView alloc] initWithFrame:view.frame]; 

    shadow.layer.contentsScale = [UIScreen mainScreen].scale;
    shadow.userInteractionEnabled = YES; // Modify this if needed
    shadow.layer.shadowColor = color;
    shadow.layer.shadowOffset = shadowOffset;
    shadow.layer.shadowRadius = shadowRadius;
    shadow.layer.masksToBounds = NO;
    shadow.clipsToBounds = NO;
    shadow.layer.shadowOpacity = shadowOpacity;
    shadow.layer.rasterizationScale = [UIScreen mainScreen].scale;
    shadow.layer.shouldRasterize = YES;

    [view.superview insertSubview:shadow belowSubview:view];
    [shadow addSubview:view];

    // Move view to the top left corner inside the shadowview 
    // ---> Buttons etc are working again :)
    view.frame = CGRectMake(0, 0, view.frame.size.width, view.frame.size.height);

    return shadow;

Related Questions

Sponsored Content

5 Answered Questions

46 Answered Questions

14 Answered Questions

[SOLVED] Rounded UIView using CALayers - only some corners - How?

21 Answered Questions

[SOLVED] Giving UIView rounded corners

3 Answered Questions

[SOLVED] UIView Round Corners with Shadow

  • 2012-07-11 17:03:51
  • azamsharp
  • 15004 View
  • 15 Score
  • 3 Answer
  • Tags:   ios

16 Answered Questions

[SOLVED] UIView with shadow, rounded corners and custom drawRect

2 Answered Questions

UIView shadow AND rounded corners

4 Answered Questions

[SOLVED] Draw a rounded UIView with gradient and drop shadow

3 Answered Questions

Sponsored Content