diff --git a/core/lib/Drupal/Core/Render/Element/Checkboxes.php b/core/lib/Drupal/Core/Render/Element/Checkboxes.php
index 8487a09..fe4a43b 100644
--- a/core/lib/Drupal/Core/Render/Element/Checkboxes.php
+++ b/core/lib/Drupal/Core/Render/Element/Checkboxes.php
@@ -122,4 +122,40 @@ public static function valueCallback(&$element, $input, FormStateInterface $form
     }
   }
 
+  /**
+   * Determines which checkboxes were checked when a form is submitted.
+   *
+   * @param array $input
+   *   An array returned by the FormAPI for a set of checkboxes.
+   *
+   * @return array
+   *   An array of keys that were checked.
+   */
+  public static function getCheckedCheckboxes(array $input) {
+    // Browsers do not include unchecked options in a form submission. The
+    // FormAPI tries to normalize this to keep checkboxes consistent with other
+    // form elements. Checkboxes show up as an array in the form of option_id =>
+    // option_id|0, where integer 0 is an unchecked option.
+    //
+    // @see \Drupal\Core\Render\Element\Checkboxes::valueCallback()
+    // @see https://www.w3.org/TR/html401/interact/forms.html#checkbox
+    $checked = array_filter($input, function($value) {
+      return $value !== 0;
+    });
+    return array_keys($checked);
+  }
+
+  /**
+   * Determines if all checkboxes in a set are unchecked.
+   *
+   * @param array $input
+   *   An array returned by the FormAPI for a set of checkboxes.
+   *
+   * @return bool
+   *   TRUE if all options are unchecked. FALSE otherwise.
+   */
+  public static function detectEmptyCheckboxes(array $input) {
+    return empty(static::getCheckedCheckboxes($input));
+  }
+
 }
diff --git a/core/modules/views/src/Form/ViewsExposedForm.php b/core/modules/views/src/Form/ViewsExposedForm.php
index bea6152..bacd554 100644
--- a/core/modules/views/src/Form/ViewsExposedForm.php
+++ b/core/modules/views/src/Form/ViewsExposedForm.php
@@ -5,6 +5,7 @@
 use Drupal\Component\Utility\Html;
 use Drupal\Core\Form\FormBase;
 use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Render\Element\Checkboxes;
 use Drupal\Core\Url;
 use Drupal\views\ExposedFormCache;
 use Symfony\Component\DependencyInjection\ContainerInterface;
@@ -146,26 +147,46 @@ public function validateForm(array &$form, FormStateInterface $form_state) {
    * {@inheritdoc}
    */
   public function submitForm(array &$form, FormStateInterface $form_state) {
+    // Form input keys that will not be included in $view->exposed_raw_data.
+    $exclude = array('submit', 'form_build_id', 'form_id', 'form_token', 'exposed_form_plugin', 'reset');
+    $values = $form_state->getValues();
     foreach (array('field', 'filter') as $type) {
       /** @var \Drupal\views\Plugin\views\ViewsHandlerInterface[] $handlers */
       $handlers = &$form_state->get('view')->$type;
       foreach ($handlers as $key => $info) {
-        $handlers[$key]->submitExposed($form, $form_state);
+        if ($handlers[$key]->acceptExposedInput($values)) {
+          $handlers[$key]->submitExposed($form, $form_state);
+        }
+        else {
+          // The input from the form did not validate, exclude it from the
+          // stored raw data.
+          $exclude[] = $key;
+        }
       }
     }
 
     $view = $form_state->get('view');
-    $view->exposed_data = $form_state->getValues();
+    $view->exposed_data = $values;
     $view->exposed_raw_input = [];
 
     $exclude = array('submit', 'form_build_id', 'form_id', 'form_token', 'exposed_form_plugin', 'reset');
-    /** @var \Drupal\views\Plugin\views\exposed_form\ExposedFormPluginInterface $exposed_form_plugin */
+    /** @var \Drupal\views\Plugin\views\exposed_form\ExposedFormPluginBase $exposed_form_plugin */
     $exposed_form_plugin = $view->display_handler->getPlugin('exposed_form');
     $exposed_form_plugin->exposedFormSubmit($form, $form_state, $exclude);
-
-    foreach ($form_state->getValues() as $key => $value) {
-      if (!in_array($key, $exclude)) {
-        $view->exposed_raw_input[$key] = $value;
+    foreach ($values as $key => $value) {
+      if (!empty($key) && !in_array($key, $exclude)) {
+        if (is_array($value)) {
+          // Handle checkboxes, we only want to include the checked options.
+          // @todo: revisit the need for this when
+          //   https://www.drupal.org/node/342316 is resolved.
+          $checked = Checkboxes::getCheckedCheckboxes($value);
+          foreach ($checked as $option_id) {
+            $view->exposed_raw_input[$option_id] = $value[$option_id];
+          }
+        }
+        else {
+          $view->exposed_raw_input[$key] = $value;
+        }
       }
     }
   }
diff --git a/core/modules/views/src/Plugin/views/filter/FilterPluginBase.php b/core/modules/views/src/Plugin/views/filter/FilterPluginBase.php
index c458e63..34b8cb4 100644
--- a/core/modules/views/src/Plugin/views/filter/FilterPluginBase.php
+++ b/core/modules/views/src/Plugin/views/filter/FilterPluginBase.php
@@ -7,6 +7,7 @@
 use Drupal\Core\Form\FormHelper;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Render\Element;
+use Drupal\Core\Render\Element\Checkboxes;
 use Drupal\user\RoleInterface;
 use Drupal\views\Plugin\views\HandlerBase;
 use Drupal\Component\Utility\Html;
@@ -1332,15 +1333,20 @@ public function storeGroupInput($input, $status) {
   }
 
   /**
-   * Check to see if input from the exposed filters should change
-   * the behavior of this filter.
+   * Determines if the input from a filter should change the generated query.
+   *
+   * @param array $input
+   *   The exposed data for this view.
+   *
+   * @return bool
+   *   TRUE if the input for this filter should be included in the view query.
+   *   FALSE otherwise.
    */
   public function acceptExposedInput($input) {
     if (empty($this->options['exposed'])) {
       return TRUE;
     }
 
-
     if (!empty($this->options['expose']['use_operator']) && !empty($this->options['expose']['operator_id']) && isset($input[$this->options['expose']['operator_id']])) {
       $this->operator = $input[$this->options['expose']['operator_id']];
     }
@@ -1358,6 +1364,12 @@ public function acceptExposedInput($input) {
           if ($value == 'All' || $value === array()) {
             return FALSE;
           }
+
+          // If checkboxes are used to render this filter, do not include the
+          // filter if no options are checked.
+          if (is_array($value) && Checkboxes::detectEmptyCheckboxes($value)) {
+            return FALSE;
+          }
         }
 
         if (!empty($this->alwaysMultiple) && $value === '') {
diff --git a/core/modules/views/src/Plugin/views/filter/InOperator.php b/core/modules/views/src/Plugin/views/filter/InOperator.php
index f3f1ca4..593e97b 100644
--- a/core/modules/views/src/Plugin/views/filter/InOperator.php
+++ b/core/modules/views/src/Plugin/views/filter/InOperator.php
@@ -282,15 +282,17 @@ public function reduceValueOptions($input = NULL) {
     return $options;
   }
 
+  /**
+   * {@inheritdoc}
+   */
   public function acceptExposedInput($input) {
-    // A very special override because the All state for this type of
-    // filter could have a default:
     if (empty($this->options['exposed'])) {
       return TRUE;
     }
 
-    // If this is non-multiple and non-required, then this filter will
-    // participate, but using the default settings, *if* 'limit is true.
+    // The "All" state for this type of filter could have a default value. If
+    // this is a non-multiple and non-required option, then this filter will
+    // participate by using the default settings *if* 'limit' is true.
     if (empty($this->options['expose']['multiple']) && empty($this->options['expose']['required']) && !empty($this->options['expose']['limit'])) {
       $identifier = $this->options['expose']['identifier'];
       if ($input[$identifier] == 'All') {
diff --git a/core/modules/views/src/Tests/Plugin/ExposedFormTest.php b/core/modules/views/src/Tests/Plugin/ExposedFormTest.php
index c5cdd08..0204468 100644
--- a/core/modules/views/src/Tests/Plugin/ExposedFormTest.php
+++ b/core/modules/views/src/Tests/Plugin/ExposedFormTest.php
@@ -207,6 +207,48 @@ public function testExposedFormRender() {
   }
 
   /**
+   * Tests overriding the default render option with checkboxes.
+   */
+  public function testExposedFormRenderCheckboxes() {
+    // Make sure we have at least two options for node type.
+    $this->drupalCreateContentType(['type' => 'page']);
+    $this->drupalCreateNode(['type' => 'page']);
+
+    // Use a test theme to convert multi-select elements into checkboxes.
+    \Drupal::service('theme_handler')->install(array('views_test_checkboxes_theme'));
+    $this->config('system.theme')
+      ->set('default', 'views_test_checkboxes_theme')
+      ->save();
+
+    // Set the "type" filter to multi-select.
+    $view = Views::getView('test_exposed_form_buttons');
+    $filter = $view->getHandler('page_1', 'filter', 'type');
+    $filter['expose']['multiple'] = TRUE;
+    $view->setHandler('page_1', 'filter', 'type', $filter);
+
+    // Only display 5 items per page so we can test that paging works.
+    $display = &$view->storage->getDisplay('default');
+    $display['display_options']['pager']['options']['items_per_page'] = 5;
+
+    $view->save();
+    $this->drupalGet('test_exposed_form_buttons');
+
+    $actual = $this->xpath('//form//input[@type="checkbox" and @name="type[article]"]');
+    $this->assertEqual(count($actual), 1, 'Article option renders as a checkbox.');
+    $actual = $this->xpath('//form//input[@type="checkbox" and @name="type[page]"]');
+    $this->assertEqual(count($actual), 1, 'Page option renders as a checkbox');
+
+    // Ensure that all results are displayed.
+    $rows = $this->xpath("//div[contains(@class, 'views-row')]");
+    $this->assertEqual(count($rows), 5, '5 rows are displayed by default on the first page when no options are checked.');
+
+    $this->clickLink('Page 2');
+    $rows = $this->xpath("//div[contains(@class, 'views-row')]");
+    $this->assertEqual(count($rows), 1, '1 row is displayed by default on the second page when no options are checked.');
+    $this->assertNoText('An illegal choice has been detected. Please contact the site administrator.');
+  }
+
+  /**
    * Tests the exposed block functionality.
    */
   public function testExposedBlock() {
diff --git a/core/modules/views/tests/themes/views_test_checkboxes_theme/views_test_checkboxes_theme.info.yml b/core/modules/views/tests/themes/views_test_checkboxes_theme/views_test_checkboxes_theme.info.yml
new file mode 100644
index 0000000..50bf73e
--- /dev/null
+++ b/core/modules/views/tests/themes/views_test_checkboxes_theme/views_test_checkboxes_theme.info.yml
@@ -0,0 +1,5 @@
+name: Views test checkboxes theme
+type: theme
+description: Theme for testing Views rendering of checkboxes.
+version: VERSION
+core: 8.x
diff --git a/core/modules/views/tests/themes/views_test_checkboxes_theme/views_test_checkboxes_theme.theme b/core/modules/views/tests/themes/views_test_checkboxes_theme/views_test_checkboxes_theme.theme
new file mode 100644
index 0000000..8673a81
--- /dev/null
+++ b/core/modules/views/tests/themes/views_test_checkboxes_theme/views_test_checkboxes_theme.theme
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * @file
+ * Changes an exposed "type" filter from a multi-select to checkboxes.
+ */
+ 
+use Drupal\Core\Form\FormStateInterface;
+
+/**
+ * Changes an exposed "type" filter from a multi-select to checkboxes.
+ */
+function views_test_checkboxes_theme_form_views_exposed_form_alter(&$form, FormStateInterface $form_state) {
+  $form['type']['#type'] = 'checkboxes';
+}
