[Mini Tutorial]
Magento Mobile Off Canvas Mini Cart

Long live mCommerce!

If you have been following me, or are subscribed to our Demac Media blog, then you most likely saw my last off canvas tutorial! If you missed it though, here’s the link: Magento Mobile Off-Canvas Navigation Menu. In that blog post I explained how user experience is one of the most important features a mobile store should focus on, as well as showing you a step-by-step example of how to create an off-canvas mobile menu. Just to make sure we’re all still on the same page, off-canvas refers to any item that sits outside of the viewport on your website through CSS or JS and slides into view once activated.

This time I mean to show you how to properly create an mobile off canvas mini cart in Magento! This post was created in conjunction with a post by our Interface Designer, Ryan Howorth on the UX Design of a Mobile Off Canvas Mini Cart

Off Canvas Mini Cart

Having an off canvas mini cart on your mobile site will fulfill the need a great number of users have, which is to be able to quickly check what is already in their cart while avoiding the aggravation caused by loading a whole new page every time they want to see this info. We can safely assume that slow loading times are one of the main causes of shopping cart abandonment. Among these reasons, a bad navigation implementation is another as explained in the related blog posts below.

A properly implemented off canvas mini cart can definitely help improve your mCommerce site’s flow, as long as you keep in mind that this feature should not increase the amount of clicks users need to perform while completing one transaction.

Related: Shopping Cart Abandonment Through the Lens of mCommerce – eCommerce Toronto Meetup.

So, let’s get started!

Files and folders that you will need to edit and/or create:

  • app/design/frontend/yourpackage/yourtheme/layout/local.xml
  • app/design/frontend/yourpackage/yourtheme/template/offcanvas
  • app/design/frontend/yourpackage/yourtheme/template/offcanvas/offcanvasright.phtml
  • app/design/frontend/yourpackage/yourtheme/template/page/html/header.phtml
  • app/design/frontend/yourpackage/yourtheme/template/page/html/mobilenav.phtml
  • app/design/frontend/yourpackage/yourtheme/template/page/1column.phtml
  • app/design/frontend/yourpackage/yourtheme/template/page/2columns-left.phtml
  • app/design/frontend/yourpackage/yourtheme/template/page/2columns-right.phtml
  • app/design/frontend/yourpackage/yourtheme/template/page/3columns.phtml
  • app/design/frontend/yourpackage/yourtheme/template/page/empty.phtml
  • skin/frontend/yourpackage/yourtheme/css/yourtheme.css

STEP 1: Declare Your Layout Blocks.

The very first thing we need to do is create an off canvas containing block (if you went through my last blog post you may have this already)

<reference name="root">
  <block type="core/text_list" name="off_canvas" as="offCanvas">
  </block>
</reference>

It needs to be created at the ‘root’ level because it will live outside of all of the content and the type=”core/text_list” tells the block to automatically display all of its children.

When something is off-canvas it can be on either the top, bottom, left or right sides, so let’s declare a block with the ‘right’ word in its name since we want our mini-cart to slide in from the right.

<reference name="root">
  <block type="core/text_list" name="off_canvas" as="offCanvas">
    <block type="core/template" name="off_canvas_right" template="offcanvas/offcanvasright.phtml">
    </block>
  </block>
</reference>

This time we give it a type=”core/template” which is the most general block type and contains all the methods we will need for this. We will create the template file later on.

Now, it is time to declare the children blocks of content that our off canvas mini cart will contain and render. This part is easy because Magento has already done it for us! We are copying and pasting the xml code used for the sidebar cart and placing it inside of our ‘off_canvas_right’ block.

<block type="checkout/cart_sidebar" name="cart_sidebar" template="checkout/cart/sidebar.phtml" before="-">
  <action method="addItemRender">
    <type>simple</type>
    <block>checkout/cart_item_renderer</block>
    <template>checkout/cart/sidebar/default.phtml</template>
  </action>
  <action method="addItemRender">
    <type>grouped</type>
    <block>checkout/cart_item_renderer_grouped</block>
    <template>checkout/cart/sidebar/default.phtml</template>
  </action>
  <action method="addItemRender">
    <type>configurable</type>
    <block>checkout/cart_item_renderer_configurable</block>
    <template>checkout/cart/sidebar/default.phtml</template>
  </action>
  <block type="core/text_list" name="topCart.extra_actions" as="extra_actions"/>
</block>

(You can find this code snippet in the checkout.xml file)

Here is The End Result:

<reference name="root">
  <block type="core/text_list" name="off_canvas" as="offCanvas">
    <block type="core/template" name="off_canvas_left" template="offcanvas/offcanvasleft.phtml">
      <block type="checkout/cart_sidebar" name="cart_sidebar" template="checkout/cart/sidebar.phtml" before="-">
        <action method="addItemRender">
          <type>simple</type>
          <block>checkout/cart_item_renderer</block>
          <template>checkout/cart/sidebar/default.phtml</template>
        </action>
        <action method="addItemRender">
          <type>grouped</type>
          <block>checkout/cart_item_renderer_grouped</block>
          <template>checkout/cart/sidebar/default.phtml</template>
        </action>
        <action method="addItemRender">
          <type>configurable</type>
          <block>checkout/cart_item_renderer_configurable</block>
          <template>checkout/cart/sidebar/default.phtml</template>
        </action>
        <block type="core/text_list" name="topCart.extra_actions" as="extra_actions"/>
      </block>
    </block>
  </block>
</reference>

Now that we have all of our off canvas blocks declared, we can proceed to declaring the block for our mobile navigation in the header.

Mobile Navigation:

This one goes outside of the <reference name=”root”></reference> block entirely and in the “header” block instead. This is where you will place the shopping cart icon, and other important mobile navigation buttons.

<reference name="header">
  <block type="core/template" name="mobile_nav" as="mobileNav" template="page/html/mobilenav.phtml"/>
</reference>

And that is it for layout!

STEP 2: Create the Template Files.

File: app/design/frontend/yourpackage/yourtheme/template/offcanvas/offcanvasright.phtml

Code:

<input type="checkbox" class="off-canvas-check" id="off-canvas-right-check">

<div id="off-canvas-right" class="off-canvas">
  <div class="main-nav-wrapper">
    <div class="off-canvas-cart">
      <?php echo $this->getChildHtml('cart_sidebar') ?>
    </div>
  </div>
</div>

The first line is a check box because we will be using the :checked pseudo class to make this mini-cart work. I’ll show you how a bit later.

After that, you can see two wrapping divs that contain the sidebar cart block.

File: app/design/frontend/yourpackage/yourtheme/template/page/html/header.phtml

Code:

<?php echo $this->getChildHtml('mobileNav'); ?>

This one is easy, you just need to call the child block we declared in the header block earlier. Preferably at the very bottom of header.phtml. You will later on show and hide this with CSS and media queries, but for anything to render we first need to create the following template file.

File: app/design/frontend/yourpackage/yourtheme/template/page/html/mobilenav.phtml

Code:

<div class="mobile-menu hide-desktop" id="icon-nav">

  <div class="left">
    <?php // You can place any other navigation buttons here ?>
  </div>

  <div class="right">
    <div class="bag-icon-wrap">
      <label for="off-canvas-right-check" id="mini-cart-icon">
        <i class="fa fa-shopping-cart"></i>
      </label>
    </div>
  </div>

</div>

I showed how to display a shopping cart item count in my other tutorial here

You will notice that inside of the ‘bag-icon-wrap’ div we have a label. This is the label that goes together with the input check box we placed inside of offcanvasright.phtml. Just make sure the ID of your check box matches the for=”” attribute of your label.

Files:
app/design/frontend/yourpackage/yourtheme/template/page/1column.phtml
app/design/frontend/yourpackage/yourtheme/template/page/2columns-left.phtml
app/design/frontend/yourpackage/yourtheme/template/page/2columns-right.phtml
app/design/frontend/yourpackage/yourtheme/template/page/3columns.phtml
app/design/frontend/yourpackage/yourtheme/template/page/empty.phtml

Code:

All of these will need the same code edit. Inside of the <body> you will need to wrap the <div class=”wrapper”> with two other wrapping divs, one called ‘outer-wrap’ and another called ‘inner-wrap’. In-between the ‘outer’ and ‘inner’ divs is where you will call the off-canvas menu block, like so:

<body<?php echo $this->getBodyClass()?' class="'.$this->getBodyClass().'"':'' ?>>
  <div id="outer-wrap" class="outer-wrap">
    <?php echo $this->getChildHtml('offCanvas') ?>
    <div id="inner-wrap" class="inner-wrap">
      <div class="wrapper">
        <?php /* Magento page content here */ ?>
      </div>
      <?php echo $this->getAbsoluteFooter() ?>
    </div>
  </div>
</body>

And that is it for templates! Now last step.

STEP 3: CSS3 Tricks.

Here is how we create the sliding animation

.mobile-menu {
  /*Styles are up to you*/
}

#off-canvas-right-check {
  display: none;
}

.outer-wrap {
  width: 100%;
  height: 100%;
  position: relative;
  overflow-x: hidden;
}

.inner-wrap {
  -webkit-transition:all 0.5s ease;
  -moz-transition:all 0.5s ease;
  -o-transition:all 0.5s ease;
  transition:all 0.5s ease;
  position: relative;
  left: 0;
}

#off-canvas-right {
  -webkit-transition:all 0.5s ease;
  -moz-transition:all 0.5s ease;
  -o-transition:all 0.5s ease;
  transition:all 0.5s ease;
  display: block;
  height: 100%;
  margin-right: -75%;
  overflow: hidden;
  position: absolute;
  right: 0;
  width: 75%;
}

#off-canvas-right-check:checked + #off-canvas-right {
  right: 75%;
  display: block;
  overflow-y: visible;
  margin-left: 0;
  z-index: 100;
}

#off-canvas-right-check:checked ~ .inner-wrap {
  position: relative;
  display: block;
  overflow-y: visible;
  z-index: 0;
  left: -75%;
}

@media only screen and (min-width:"940px") {

  .mobile-menu,
  #icon-nav {
    display: none;
  }

  #off-canvas-right-check:checked + #off-canvas-right {
    display: none;
  }

  #off-canvas-right-check:checked ~ .inner-wrap {
    left: 0;
  }
}

Lines 5-7:
We don’t want or need to see the check box, so we better display:none it.

Lines 9-23:
Just some styles and transitions for the wrappers to work better with the off-canvas menu. For the outer-wrap we did overflow-x:hidden to avoid getting a scrolling bar once the off-canvas is open. For the inner-wrap we added a left:0 for the animation to have a starting position.

Lines 25-37:
This is our off-canvas menu. The first part here is, of course, the transitions that will allow the sliding animation to happen. We use position:absolute to position the mini-cart out of the html structure and on top of everything else, height:100% to make it reach the bottom of the window at all times, and overflow:hidden so that we can put it outside of its container box without increasing the container’s width. Then we give it a 75% width and a right margin of the same amount but negative so that it’s fully hidden outside of the browser.

Lines 39-45:
Here is where we finally get to use the magic of CSS3. We use the pseudo-class :checked to target the check box when checked. It’ll be checked when the user taps the label that is related to it (the shopping cart icon is the label). We use the ‘+’ selector to target only the immediate sibling element with the ‘off-canvas-right’ id, and then add the necessary styles for it to slide to the left.

Lines 47-53:
Here we use the :checked pseudo-class again but this time we use the ‘~’ selector which targets any next siblings with the class ‘inner-wrap’ which is the site’s content wrap. We want to simultaneously slide this to the left while the off-canvas slides to the left from the right as well. We need left:-75% so that they both move the same distance and look synced. We need position:relative here for left:-75% to work.

Lines 55-69:
And finally some media queries to hide the mobile navigation and off-canvas menu from 940px and up. We also want to return ‘inner-wrap’ to left:0. The transitions will make it look nice when you’re resizing the browser window.

Related: Go Mobile Or Go Home!

Hopefully, this tutorial helps you with implementing an off canvas mini cart for your online store. Remember that mCommerce is the here and now and you should be executing strategies to integrate and optimize the performance of your store on mobile. Comment below if you have any questions or would like clarification on any of the steps I’ve outlined above!