iOS
UIView
drop shadow
Swift
app development

What's the best way to add a drop shadow to my UIView

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

The best way to add a shadow to a UIView is usually to configure its backing layer directly and be explicit about shape and performance. A shadow can look correct in a few lines, but getting it to behave well with rounded corners, scrolling, and Auto Layout takes a bit more care.

Use the View's Layer, Not a Custom Drawing Hack

Every UIView has a CALayer, and shadows are layer properties. For most cases you do not need custom drawing or extra image assets.

swift
1import UIKit
2
3final class ShadowDemoViewController: UIViewController {
4    override func viewDidLoad() {
5        super.viewDidLoad()
6
7        let card = UIView(frame: CGRect(x: 40, y: 120, width: 240, height: 120))
8        card.backgroundColor = .white
9        card.layer.cornerRadius = 16
10        card.layer.shadowColor = UIColor.black.cgColor
11        card.layer.shadowOpacity = 0.18
12        card.layer.shadowOffset = CGSize(width: 0, height: 8)
13        card.layer.shadowRadius = 16
14
15        view.backgroundColor = .systemGroupedBackground
16        view.addSubview(card)
17    }
18}

These properties control the visual result:

  • 'shadowColor sets the color'
  • 'shadowOpacity controls visibility'
  • 'shadowOffset controls direction and distance'
  • 'shadowRadius controls blur'

This is the right starting point, but it is not the whole story.

Add a shadowPath for Performance

Without a shadow path, Core Animation may need to calculate the shadow shape dynamically. That is slower than giving the system the exact outline.

swift
1final class ShadowCardView: UIView {
2    override init(frame: CGRect) {
3        super.init(frame: frame)
4        commonInit()
5    }
6
7    required init?(coder: NSCoder) {
8        super.init(coder: coder)
9        commonInit()
10    }
11
12    private func commonInit() {
13        backgroundColor = .white
14        layer.cornerRadius = 16
15        layer.shadowColor = UIColor.black.cgColor
16        layer.shadowOpacity = 0.18
17        layer.shadowOffset = CGSize(width: 0, height: 8)
18        layer.shadowRadius = 16
19    }
20
21    override func layoutSubviews() {
22        super.layoutSubviews()
23        layer.shadowPath = UIBezierPath(
24            roundedRect: bounds,
25            cornerRadius: layer.cornerRadius
26        ).cgPath
27    }
28}

Setting the path inside layoutSubviews is important because the view's size may change after Auto Layout runs.

Rounded Corners and Shadows Need Separate Responsibilities

One of the most common problems is combining rounded corners and clipping on the same layer that draws the shadow. If masksToBounds is true, the shadow gets clipped away.

The usual fix is to use two views:

  • an outer container that owns the shadow
  • an inner content view that clips to rounded corners
swift
1import UIKit
2
3final class CardContainerView: UIView {
4    private let content = UIView()
5
6    override init(frame: CGRect) {
7        super.init(frame: frame)
8        setup()
9    }
10
11    required init?(coder: NSCoder) {
12        super.init(coder: coder)
13        setup()
14    }
15
16    private func setup() {
17        layer.shadowColor = UIColor.black.cgColor
18        layer.shadowOpacity = 0.16
19        layer.shadowOffset = CGSize(width: 0, height: 6)
20        layer.shadowRadius = 12
21
22        content.backgroundColor = .white
23        content.layer.cornerRadius = 16
24        content.layer.masksToBounds = true
25
26        addSubview(content)
27    }
28
29    override func layoutSubviews() {
30        super.layoutSubviews()
31        content.frame = bounds
32        layer.shadowPath = UIBezierPath(roundedRect: bounds, cornerRadius: 16).cgPath
33    }
34}

This pattern is more reliable than trying to make one layer do both jobs.

Tune the Shadow to Match the Design

Most shadows look bad because the opacity is too high or the offset is too dramatic. A modern iOS shadow usually works better with:

  • low opacity
  • moderate blur
  • vertical offset greater than horizontal offset

Good defaults for a card-like component are often:

  • opacity between 0.10 and 0.22
  • radius between 8 and 20
  • offset around 0, 4 to 0, 10

Use the smallest shadow that still communicates depth. Heavy shadows can make the interface look muddy.

When Rasterization Helps

If a complex shadowed view is animating or appears in a scrolling list, rasterization can help in some cases. Use it carefully, because it trades CPU work for cached bitmap memory.

swift
layer.shouldRasterize = true
layer.rasterizationScale = UIScreen.main.scale

Only do this after profiling. It is not a default recommendation for every shadowed view.

Common Pitfalls

The most common mistake is enabling masksToBounds on the same layer that should display the shadow. That clips the shadow completely.

Another issue is forgetting to update shadowPath when the view resizes. Shadows then look wrong or performance drops because Core Animation must infer the shape repeatedly.

A third problem is overdesigning the effect. Large blur radii and dark shadows look artificial and can make text or controls feel less sharp.

Summary

  • Add shadows through the view's layer, not through custom image tricks.
  • Set a shadowPath whenever the shape is known.
  • Use a container view for the shadow and an inner view for rounded clipped content.
  • Keep opacity and blur restrained for a cleaner iOS look.
  • Profile before enabling rasterization or other performance tweaks.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.