Create a Cool 3D Sidebar Menu Animation

In this tutorial, you’ll learn how to manipulate CALayer properties on views in order to create a cool 3D sidebar animation. By Warren Burton.

Leave a rating/review
Download materials
Save for later
Update note: Warren Burton updated this tutorial for iOS 12 and Swift 5. Audrey Tam wrote the original.

Many iOS apps need a menu to navigate between views or to let the user make choices. One commonly used design is a side menu.

You can easily make a side menu using a simple form, but how can you introduce a little delight into your UI? You want to put a smile on your users’ faces and bring them back to your app time and time again. One way to do this this is by creating a 3D sidebar animation.

In this tutorial, you’ll learn how to animate some UIView elements by manipulating CALayer properties to create a 3D sidebar animation. This animation was inspired by a To-Do app called Taasky.

3D sidebar animation

Throughout this tutorial, you’ll work with the following elements:

  • Storyboards
  • Auto Layout constraints
  • UIScrollView
  • View controller containment
  • Core Animation

If these elements sound unfamiliar, then you should start with some of our other iOS tutorials before returning to this one.

Getting Started

Before you begin, download the starter project, called TaskChooser, by using the Download Materials button at the top or bottom of this page.

Imagine you are creating a basic app for negotiating events with your colleagues or friends. Thumbs-up if you’re in, thumbs-down if you can’t make it. You can even decline due to inclement weather.

Take a moment to look at the project. You’ll see it’s a standard Xcode Master-Detail template app that displays a table of images.

  • MenuViewController: A UITableViewController that uses a custom table view cell, MenuItemCell, to set the background color of each cell. It also has an image.
  • MenuDataSource: An object that implements UITableViewDataSource to provide the table data from MenuItems.json. This data could come from a server in a production situation.
  • DetailViewController: Displays a large image using the same background color as a cell that you’ve selected.

Build and run the app. You should see the starter project load with 7 rows of color and icons:

3D sidebar animation

Use the menu to display which option you’ve selected:

3D sidebar animation

This is functional, but the look and feel is rather ordinary. You want your app to both amaze and delight!

In this tutorial, you’ll refactor the Master-Detail app into a horizontal scroll view. You’ll embed the master and detail views inside container views.

Next, you’ll add a button to show or hide the menu. You’ll then add a neat 3D folding effect on the menu.

As a final touch for this 3D animation sidebar, you’ll rotate the menu button in sync with showing or hiding the menu.

Your first task is to convert MenuViewController and DetailViewController to a slide-out sidebar, where a scroll view contains the menu and detail views side-by-side.

Restructuring Your Storyboard

Before you can rebuild your menu, you need to do a little demolition. Time to pull out the sledgehammer and the safety glasses. :]

Open Main.storyboard in the Views folder of the Project navigator. You can see UINavigationController, MenuViewController and DetailViewController connected by segues:

3D sidebar animation

Deleting the Old Structure

The Navigation Controller Scene does not spark joy. Select that scene and delete it. Next, select the segue between MenuViewController and DetailViewController and delete that, too.

With that done, brush the dust off and get to work. :]

3D sidebar animation

Adding a New Root Container

Since UINavigationController is gone, you no longer have a top-level container for the view controllers in the project. You’ll add one now.

Select the Views folder in the Project navigator. Add a new file to the project by pressing Command-N. Then:

3D sidebar animation

  1. Select iOSCocoa Touch Class. Click Next.
  2. Name the class RootViewController.
  3. Ensure that RootViewController is a subclass of UIViewController.
  4. Make sure “Also create XIB file” is not checked.
  5. The language should be Swift.

3D sidebar animation

Open Main.storyboard again.

Open the Object Library with the key shortcut Command-Shift-L and drag an instance of UIViewController to the storyboard.

3D sidebar animation

Select View Controller Scene from the Object hierarchy, then open the Identity inspector. Set the Class field to RootViewController.

3D sidebar animation

Next, open the Attributes inspector and check the Is Initial View Controller box.

3D sidebar animation

Adding Identifiers to View Controllers

Since MenuViewController and DetailViewController are no longer connected by segues, you need a way of accessing them from your code. So, your next step is to provide some identifiers to do this.

Select Menu View Controller Scene from the Object hierarchy. Open the Identity inspector and set Storyboard ID to MenuViewController.

This string can be any sensible value, but an easy-to-remember technique is to use the name of the class.

3D sidebar animation

Next, select Detail View Controller Scene from the Object hierarchy and do the same thing. Set Storyboard ID to DetailViewController.

3D sidebar animation

That’s all you need to do in Main.storyboard. The rest of this tutorial will be in code.

Creating Contained View Controllers

In this section, you’ll create a UIScrollView and add two containers to that scroll view. The containers will hold MenuViewController and DetailViewController.

Creating a Scroll View

Your first step is to create a UIScrollView.

Open RootViewController.swift in the Project navigator. Delete everything that Xcode supplied from the inside of RootViewController.

Add this extension above RootViewController:

extension UIView {
  func embedInsideSafeArea(_ subview: UIView) {
    subview.translatesAutoresizingMaskIntoConstraints = false
    subview.leadingAnchor.constraint(equalTo: safeAreaLayoutGuide.leadingAnchor)
      .isActive = true
    subview.trailingAnchor.constraint(equalTo: safeAreaLayoutGuide.trailingAnchor)
      .isActive = true
    subview.topAnchor.constraint(equalTo: safeAreaLayoutGuide.topAnchor)
      .isActive = true
    subview.bottomAnchor.constraint(equalTo: safeAreaLayoutGuide.bottomAnchor)
      .isActive = true

This is a helper that you’ll use a few times in this tutorial. The code adds the passed-in view as a subview, then adds four constraints to glue the subview inside itself.

Next add this extension at the end of the file:

extension RootViewController: UIScrollViewDelegate {

You’ll want to watch UIScrollView for changes. That action comes later in the tutorial, so this extension is empty for now.

Finally, insert the following code inside of RootViewController:

// 1
lazy var scroller: UIScrollView = {
  let scroller = UIScrollView(frame: .zero)
  scroller.isPagingEnabled = true
  scroller.delaysContentTouches = false
  scroller.bounces = false
  scroller.showsHorizontalScrollIndicator = false
  scroller.delegate = self
  return scroller
// 2
override func viewDidLoad() {
  view.backgroundColor = UIColor(named: "rw-dark")
// 3
override var preferredStatusBarStyle: UIStatusBarStyle {
  return .lightContent

Here’s what you’re doing in this code:

  1. First, you create a UIScrollView. You want to enable paging so that the content moves in atomic units inside the scroll view. You’ve disabled delaysContentTouches so that the inner controllers will react quickly to user touches. bounces is set to false so you don’t get a stretchy feel from the scroller. You then set RootViewController as the delegate of the scroll view.
  2. In viewDidLoad(), you set the background color and embed the scroll view inside the root view using the helper you added before.
  3. An override to preferredStatusBarStyle allows the status bar to appear light on the dark background.

Build and run your app to show that it launches properly after this refactor:

3D sidebar animation

Since you haven’t added the buttons and content to the new RootViewController, you should only see the dark background you have set. Don’t worry, you’ll add them back in the next section.