diff --git a/includes/wizard.inc b/includes/wizard.inc
index 50cd79c..eec0063 100644
--- a/includes/wizard.inc
+++ b/includes/wizard.inc
@@ -254,21 +254,41 @@ function ctools_wizard_wrapper($form, &$form_state) {
     }
 
     if (!empty($form_info['show trail'])) {
+      $element = array(
+        '#theme_wrappers' => array('ctools_wizard_trail_wrapper'),
+        '#attributes' => array('class' => array($class)),
+        '#form_state' => $form_state,
+        '#step' => $id,
+      );
+
       if (!empty($form_info['free trail'])) {
         // ctools_wizard_get_path() returns results suitable for #redirect
         // which can only be directly used in drupal_goto. We have to futz
         // with it.
         $path = ctools_wizard_get_path($form_info, $id);
-        $options = array();
+
+        // Add link element.
+        $options = array(
+          'html' => FALSE,
+          'attributes' => array(),
+        );
         if (!empty($path[1])) {
           $options['query'] = $path[1];
         }
         if (!empty($path[2])) {
           $options['fragment'] = $path[2];
         }
-        $title = l($title, $path[0], $options);
+
+        $element['#theme'] = 'link';
+        $element['#text'] = $title;
+        $element['#path'] = $path[0];
+        $element['#options'] = $options;
+      }
+      else {
+        $element['#markup'] = $title;
       }
-      $trail[] = '<span class="' . $class . '">' . $title . '</span>';
+
+      $trail[] = $element;
     }
   }
 
diff --git a/includes/wizard.theme.inc b/includes/wizard.theme.inc
index 304906c..c1b91b4 100644
--- a/includes/wizard.theme.inc
+++ b/includes/wizard.theme.inc
@@ -10,16 +10,36 @@ function ctools_wizard_theme(&$theme) {
     'variables' => array('trail' => NULL),
     'file' => 'includes/wizard.theme.inc',
   );
+  $theme['ctools_wizard_trail_wrapper'] = array(
+    'render element' => 'element',
+    'file' => 'includes/wizard.theme.inc',
+  );
 }
 
 /**
- * Themable display of the 'breadcrumb' trail to show the order of the
- * forms.
+ * Displays the 'breadcrumb' trail to show the order of the forms.
+ * @ingroup themable
  */
 function theme_ctools_wizard_trail($vars) {
   $trail = $vars['trail'];
   if (!empty($trail)) {
-    return '<div class="wizard-trail">' . implode(' » ', $trail) . '</div>';
+    $output = array();
+    foreach (element_children($trail) as $key) {
+      $output[] = drupal_render($trail[$key]);
+    }
+    return '<div class="wizard-trail">' . implode(' » ', $output) . '</div>';
   }
 }
 
+/**
+ * Theme wrapper for the individual 'breadcrumb' trail items.
+ * @ingroup themable
+ */
+function theme_ctools_wizard_trail_wrapper($vars) {
+  $element = $vars['element'];
+  $output = '<span' . drupal_attributes($element['#attributes']) . '>';
+  $output .= $element['#children'];
+  $output .= "</span>\n";
+
+  return $output;
+}
