diff --git a/checklistapi.api.php b/checklistapi.api.php
index bc02a71..a8352f5 100644
--- a/checklistapi.api.php
+++ b/checklistapi.api.php
@@ -52,6 +52,10 @@
  *         This is useful for automatically checking items that can be
  *         programmatically tested (e.g. a module is installed or a variable has
  *         a certain value).
+ *       - #optional: (optional) Allow the task to be marked as optional. Can
+ *         be Boolean or string. Setting to TRUE will result in the default
+ *         label 'n/a' for an additional checkbox added to designate the task
+ *         as ignored. Setting this to a string will use the value as the label.
  *       - #weight: (optional) A floating point number used to sort the list of
  *         items before being output. Lower numbers appear before higher
  *         numbers.
diff --git a/checklistapi.css b/checklistapi.css
index b7cc6ea..8e8fc9c 100644
--- a/checklistapi.css
+++ b/checklistapi.css
@@ -23,3 +23,16 @@
 #checklistapi-checklist-form .progress .filled {
   background-image: none;
 }
+
+/**
+ * Optional tasks
+ */
+.checklistapi-title-ignored {
+  text-decoration: line-through;
+}
+div.form-checkboxes.checklistapi-item-optional div:first-child+div {
+  padding-left: 1em;
+}
+div.form-checkboxes.checklistapi-item-optional div:first-child+div label {
+  opacity: 0.66;
+}
diff --git a/checklistapi.js b/checklistapi.js
index c4c3707..be225a1 100644
--- a/checklistapi.js
+++ b/checklistapi.js
@@ -7,18 +7,44 @@
   Drupal.behaviors.checklistapiFieldsetSummaries = {
     attach: function (context) {
       $('#checklistapi-checklist-form .vertical-tabs-panes > fieldset', context).drupalSetSummary(function (context) {
-        var total = $(':checkbox.checklistapi-item', context).size(), args = {};
+        var total = $(':checkbox.checklistapi-item:first-child', context).size(), args = {};
+        var optional = $(':checkbox.checklistapi-item-optional[value$="_ignored"]', context).size();
+        var ignored = $(':checkbox.checklistapi-item-optional:checked[value$="_ignored"]', context).size();
         if (total) {
-          args['@complete'] = $(':checkbox.checklistapi-item:checked', context).size();
-          args['@total'] = total;
-          args['@percent'] = Math.round(args['@complete'] / args['@total'] * 100);
-          return Drupal.t('@complete of @total (@percent%)', args);
+          args['@ignored'] = ignored ? Drupal.t(", @num ignored", {'@num':ignored}) : '';
+          args['@complete'] = $(':checkbox.checklistapi-item:checked', context).size() - ignored;
+          // Optional task have 2 checkboxes, but they should only count as 1.
+          args['@total'] = total - ignored - optional;
+          // If all tasks are ignored, treat as complete.
+          args['@percent'] = args['@total'] == 0 ? 100 : Math.round(args['@complete'] / args['@total'] * 100);
+          return Drupal.t('@complete of @total (@percent%@ignored)', args);
         }
       });
     }
   };
 
   /**
+   * Toggle controls for optional tasks.
+   */
+  Drupal.behaviors.checklistapiIgnoredTasks = {
+    attach: function () {
+      function ignoreTaskToggle(element) {
+        var ignore = element.children().last().find('input');
+        var task = element.children().first().find('input');
+        if (ignore.attr('checked')) { task.attr('disabled', 'true').next().addClass('checklistapi-title-ignored'); }
+        else { task.removeAttr('disabled').next().removeClass('checklistapi-title-ignored'); }
+
+        if (task.attr('checked')) { ignore.parent().hide(); }
+        else { ignore.parent().show(); }
+      }
+      var optional = $('#checklistapi-checklist-form div.checklistapi-item-optional');
+      optional.click( function () { ignoreTaskToggle($(this)); });
+      // Fake a click to process initial state.
+      optional.trigger('click');
+    }
+  };
+
+  /**
    * Adds dynamic item descriptions toggling.
    */
   Drupal.behaviors.checklistapiCompactModeLink = {
diff --git a/checklistapi.pages.inc b/checklistapi.pages.inc
index 3a99cf8..d0ab61c 100644
--- a/checklistapi.pages.inc
+++ b/checklistapi.pages.inc
@@ -100,7 +100,7 @@ function checklistapi_checklist_form($form, &$form_state, $id, $field_data = arr
       $saved_item = !empty($checklist->savedProgress[$item_key]) ? $checklist->savedProgress[$item_key] : 0;
       // Build title.
       $title = filter_xss($item['#title']);
-      if ($saved_item) {
+      if (isset($saved_item['#completed'])) {
         // Append completion details.
         $user = user_load($saved_item['#uid']);
         $title .= t(
@@ -142,6 +142,52 @@ function checklistapi_checklist_form($form, &$form_state, $id, $field_data = arr
         '#title' => filter_xss_admin($title),
         '#type' => 'checkbox',
       );
+      // Add an optional N/A checkbox
+      if (isset($item['#optional'])) {
+        $ignored_key = $item_key . '_ignored';
+        $ignored = isset($saved_item[$ignored_key]['#ignored']) ? $saved_item[$ignored_key] : FALSE;
+        $optional_text = $item['#optional'] === TRUE ? t('n/a') : filter_xss_admin($item['#optional']);
+        // Switch checkbox element to checkboxes
+        unset($form['checklistapi'][$group_key][$item_key]['#title']);
+        $form['checklistapi'][$group_key][$item_key]['#type'] = 'checkboxes';
+        $form['checklistapi'][$group_key][$item_key]['#tree'] = TRUE;
+        $form['checklistapi'][$group_key][$item_key]['#attributes'] = array('class' => array('checklistapi-item', 'checklistapi-item-optional'));
+        // Used $saved_item if available
+        $default_value = array();
+        if (isset($saved_item[$item_key]['#completed'])) {
+          $default_value[$item_key] = $item_key;
+        }
+        if ($ignored) {
+          $default_value[$ignored_key] = $ignored_key;
+        }
+        $form['checklistapi'][$group_key][$item_key]['#default_value'] = $default_value;
+        // Append completion details.
+        if (isset($saved_item[$item_key]['#completed'])) {
+          $user = user_load($saved_item[$item_key]['#uid']);
+          $title .= t(
+            '<span class="completion-details"> - Completed @time by !user</a>',
+            array(
+              '@time' => format_date($saved_item[$item_key]['#completed'], 'short'),
+              '!user' => theme('username', array('account' => $user)),
+            )
+          );
+        }
+        // Append ignore details.
+        elseif ($ignored) {
+          $user = user_load($ignored['#uid']);
+          $optional_text .= t(
+            '<span class="completion-details"> - Ignored @time by !user</a>',
+            array(
+              '@time' => format_date($ignored['#ignored'], 'short'),
+              '!user' => theme('username', array('account' => $user)),
+            )
+          );
+        }
+        $form['checklistapi'][$group_key][$item_key]['#options'] = array(
+          $item_key => filter_xss_admin($title),
+          $ignored_key => filter_xss_admin($optional_text),
+        );
+      }
     }
   }
 
diff --git a/checklistapi_example/checklistapi_example.module b/checklistapi_example/checklistapi_example.module
index ca3a964..7930f77 100644
--- a/checklistapi_example/checklistapi_example.module
+++ b/checklistapi_example/checklistapi_example.module
@@ -273,12 +273,14 @@ function checklistapi_example_checklistapi_checklist_info_alter(&$definitions) {
         "I'm !chx.",
         array('!chx' => l(t('chx'), 'http://drupal.org/user/9446'))
       ),
+      '#optional' => TRUE,
     ),
   );
   $definitions['example_checklist']['understand_all_core_patch_implications'] = array(
     '#title' => t('I understand all implications of a core patch'),
     'im_chuck_norris' => array(
       '#title' => t("I'm Chuck Norris."),
+      '#optional' => t('Even Chuck Norris isn\'t Chuck Norris.'),
     ),
   );
 }
diff --git a/lib/Drupal/checklistapi/ChecklistapiChecklist.php b/lib/Drupal/checklistapi/ChecklistapiChecklist.php
index 7a732e4..7d807da 100644
--- a/lib/Drupal/checklistapi/ChecklistapiChecklist.php
+++ b/lib/Drupal/checklistapi/ChecklistapiChecklist.php
@@ -124,6 +124,12 @@ class ChecklistapiChecklist {
     else {
       $this->savedProgress = variable_get($this->getSavedProgressVariableName(), array());
     }
+    // Remove ignored tasks from total items.
+    foreach ($this->savedProgress as $name => $task) {
+      if (is_array($task) && isset($task[$name . '_ignored']['#ignored'])) {
+        $this->numberOfItems--;
+      }
+    }
   }
 
   /**
@@ -253,7 +259,8 @@ class ChecklistapiChecklist {
           continue;
         }
         $old_item = (!empty($this->savedProgress[$item_key])) ? $this->savedProgress[$item_key] : 0;
-        if ($item == 1) {
+        $ignored_key = $item_key . '_ignored';
+        if ($item === 1) {
           // Item is checked.
           $progress['#completed_items']++;
           if ($old_item) {
@@ -269,6 +276,54 @@ class ChecklistapiChecklist {
             $num_changed_items++;
           }
         }
+        elseif (is_array($item) && array_key_exists($ignored_key, $item)) {
+          // Handle optional items, whose '#type' will be 'checkboxes'.
+          if ($item[$item_key] === $item_key) {
+            // Item is completed
+            $progress['#completed_items']++;
+            if (isset($old_item[$item_key]) && $old_item[$item_key]) {
+              // Item was previously checked. Use saved value.
+              $new_item[$item_key] = $old_item[$item_key];
+            }
+            else {
+              // Item is newly checked. Set new value.
+              $new_item = array(
+                $item_key => array(
+                  '#completed' => $time,
+                  '#uid' => $user->uid,
+                ),
+              );
+              $num_changed_items++;
+            }
+            // Completed items are not ignored
+            $new_item[$ignored_key] = 0;
+          }
+          elseif (isset($item[$ignored_key]) && $item[$ignored_key]) {
+            // Item was ignored.
+            if (isset($old_item[$ignored_key]) && $old_item[$ignored_key]) {
+              // Item was previously ignored. Use saved value.
+              $new_item[$ignored_key] = $old_item[$ignored_key];
+            }
+            else {
+              // Item is newly ignored. Set new value.
+              $new_item = array(
+                $ignored_key => array(
+                  '#ignored' => $time,
+                  '#uid' => $user->uid,
+                )
+              );
+              $num_changed_items++;
+            }
+          }
+          else {
+            // Neither are checked
+            $new_item = 0;
+            if ($old_item) {
+              // Item was previously checked.
+              $num_changed_items++;
+            }
+          }
+        }
         else {
           // Item is unchecked.
           $new_item = 0;
