Index: src/wp-admin/css/customize-controls.css
===================================================================
--- src/wp-admin/css/customize-controls.css	(revision 36506)
+++ src/wp-admin/css/customize-controls.css	(working copy)
@@ -1311,6 +1311,123 @@
 	color: #00a0d2;
 }
 
+/* Device/preview size toggles */
+
+.wp-full-overlay {
+	background: #191e23;
+}
+
+#customize-preview.wp-full-overlay-main {
+	background-color: #f1f1f1;
+}
+
+.expanded #customize-footer-actions {
+	position: fixed;
+	bottom: 0;
+	left: 0;
+	width: 300px;
+	height: 45px;
+	border-top: 1px solid #ddd;
+}
+
+#customize-footer-actions .devices {
+	float: right;
+}
+
+#customize-footer-actions .devices button {
+	cursor: pointer;
+	background: transparent;
+	border: none;
+	height: 45px;
+	padding: 0 3px;
+	margin: 0 0 0 -4px;
+	box-shadow: none;
+	border-top: 1px solid transparent;
+	border-bottom: 4px solid transparent;
+	-webkit-transition: all .1s ease-in-out;
+	transition: all .1s ease-in-out;
+}
+
+#customize-footer-actions .devices button:focus {
+	box-shadow: none;
+	outline: none;
+}
+
+#customize-footer-actions .devices button:before {
+	display: inline-block;
+	-webkit-font-smoothing: antialiased;
+	font: normal 20px/30px "dashicons";
+	vertical-align: top;
+	margin: 3px 0;
+	padding: 4px 8px;
+	color: #656a6f;
+}
+
+#customize-footer-actions .devices button.active {
+	border-bottom-color: #191e23;
+}
+
+#customize-footer-actions .devices button:hover,
+#customize-footer-actions .devices button:focus {
+	background-color: #fff;
+	border-bottom-color: #0073aa;
+}
+
+#customize-footer-actions .devices button.active:before,
+#customize-footer-actions .devices button:hover:before,
+#customize-footer-actions .devices button:focus:before {
+	color: #191e23;
+}
+
+.wp-core-ui .wp-full-overlay .collapse-sidebar:hover,
+.wp-core-ui .wp-full-overlay .collapse-sidebar:focus {
+	color: #191e23;
+}
+
+#customize-footer-actions .devices .preview-desktop:before {
+	content: "\f472";
+}
+
+#customize-footer-actions .devices .preview-tablet:before {
+	content: "\f471";
+}
+
+#customize-footer-actions .devices .preview-mobile:before {
+	content: "\f470";
+}
+
+@media screen and (max-width:1024px) {
+	#customize-footer-actions .devices {
+		display: none;
+	}
+}
+
+.collapsed #customize-footer-actions .devices button:before {
+	display: none;
+}
+
+.collapsed #customize-footer-actions .devices .preview-full {
+	left: 0;
+}
+
+.preview-mobile #customize-preview {
+	margin: auto 0 auto -160px;
+	width: 320px;
+	height: 480px;
+	max-height: 100%;
+	max-width: 100%;
+	left: 50%;
+}
+
+.preview-tablet #customize-preview {
+	margin: auto 0 auto -3in;
+	width: 6in;
+	height: 9in;
+	max-height: 100%;
+	max-width: 100%;
+	left: 50%;
+}
+
 .widget-reorder-nav span,
 .menu-item-reorder-nav button {
 	position: relative;
Index: src/wp-admin/customize.php
===================================================================
--- src/wp-admin/customize.php	(revision 36506)
+++ src/wp-admin/customize.php	(working copy)
@@ -137,7 +137,7 @@
 					<button class="customize-help-toggle dashicons dashicons-editor-help" aria-expanded="false"><span class="screen-reader-text"><?php _e( 'Help' ); ?></span></button>
 				</div>
 				<div class="customize-panel-description"><?php
-					_e( 'The Customizer allows you to preview changes to your site before publishing them. You can also navigate to different pages on your site to preview them.' );
+					_e( 'The Customizer allows you to preview changes to your site before publishing them. You can navigate to different pages on your site to preview them.' );
 				?></div>
 			</div>
 
@@ -148,6 +148,24 @@
 		</div>
 
 		<div id="customize-footer-actions" class="wp-full-overlay-footer">
+			<?php $previewable_devices = $wp_customize->get_previewable_devices(); ?>
+			<?php if ( ! empty( $previewable_devices ) ) : ?>
+			<div class="devices">
+				<?php foreach ( $previewable_devices as $device => $settings ) : ?>
+					<?php
+					$active = ! empty( $settings['default'] );
+					$class = "preview-$device";
+					if ( $active ) {
+						$class .= ' active';
+					}
+					$aria_pressed = $active ? 'true' : 'false';
+					?>
+					<button type="button" class="<?php echo esc_attr( $class ); ?>" aria-pressed="<?php echo esc_attr( $aria_pressed ) ?>" data-device="<?php echo esc_attr( $device ); ?>">
+						<span class="screen-reader-text"><?php echo esc_html( $settings['label'] ); ?></span>
+					</button>
+				<?php endforeach; ?>
+			</div>
+			<?php endif; ?>
 			<button type="button" class="collapse-sidebar button-secondary" aria-expanded="true" aria-label="<?php esc_attr_e( 'Collapse Sidebar' ); ?>">
 				<span class="collapse-sidebar-arrow"></span>
 				<span class="collapse-sidebar-label"><?php _e( 'Collapse' ); ?></span>
Index: src/wp-admin/js/customize-controls.js
===================================================================
--- src/wp-admin/js/customize-controls.js	(revision 36506)
+++ src/wp-admin/js/customize-controls.js	(working copy)
@@ -3229,7 +3229,8 @@
 			overlay = body.children( '.wp-full-overlay' ),
 			title = $( '#customize-info .panel-title.site-title' ),
 			closeBtn = $( '.customize-controls-close' ),
-			saveBtn = $( '#save' );
+			saveBtn = $( '#save' ),
+			footerActions = $( '#customize-footer-actions' );
 
 		// Prevent the form from saving when enter is pressed on an input or select element.
 		$('#customize-controls').on( 'keydown', function( e ) {
@@ -3605,6 +3606,28 @@
 			event.preventDefault();
 		});
 
+		// Preview size toggles.
+		api.previewedDevice = new api.Value();
+		footerActions.find( '.devices button' ).on( 'click', function( event ) {
+			api.previewedDevice.set( $( event.currentTarget ).data( 'device' ) );
+		});
+
+		api.previewedDevice.bind( function( newDevice ) {
+			var overlay = $( '.wp-full-overlay' ), devices = '';
+			footerActions.find( '.devices button' )
+				.removeClass( 'active' )
+				.attr( 'aria-pressed', false );
+			$.each( api.settings.previewableDevices, function( device ) {
+				devices = devices + ' preview-' + device;
+			} );
+			overlay
+				.removeClass( devices )
+				.addClass( 'preview-' + newDevice );
+			footerActions.find( '.devices .preview-' + newDevice )
+				.addClass( 'active' )
+				.attr( 'aria-pressed', true );
+		} );
+
 		// Bind site title display to the corresponding field.
 		if ( title.length ) {
 			api( 'blogname', function( setting ) {
Index: src/wp-includes/class-wp-customize-manager.php
===================================================================
--- src/wp-includes/class-wp-customize-manager.php	(revision 36506)
+++ src/wp-includes/class-wp-customize-manager.php	(working copy)
@@ -1710,6 +1710,7 @@
 			'nonce'    => $this->get_nonces(),
 			'autofocus' => array(),
 			'documentTitleTmpl' => $this->get_document_title_template(),
+			'previewableDevices' => $this->get_previewable_devices(),
 		);
 
 		// Prepare Customize Section objects to pass to JavaScript.
@@ -1787,6 +1788,40 @@
 	}
 
 	/**
+	 * Returns a list of devices to allow previewing.
+	 *
+	 * @access public
+	 * @since 4.5.0
+	 * @return array List of devices with labels and default setting.
+	 */
+	public function get_previewable_devices() {
+		$devices = array(
+			'desktop' => array(
+				'label' => __( 'Enter desktop preview mode' ),
+				'default' => true,
+			),
+			'tablet' => array(
+				'label' => __( 'Enter tablet preview mode' ),
+			),
+			'mobile' => array(
+				'label' => __( 'Enter mobile preview mode' ),
+			),
+		);
+
+		/**
+		 * Filter the available devices to allow previewing in the Customizer.
+		 *
+		 * @since 4.5.0
+		 *
+		 * @see WP_Customize_Manager::get_previewable_devices()
+		 *
+		 * @param array $devices List of devices with labels and default setting.
+		 */
+		$devices = apply_filters( 'customize_previewable_devices', $devices );
+		return $devices;
+	}
+
+	/**
 	 * Register some default controls.
 	 *
 	 * @since 3.4.0
Index: tests/phpunit/tests/customize/manager.php
===================================================================
--- tests/phpunit/tests/customize/manager.php	(revision 36506)
+++ tests/phpunit/tests/customize/manager.php	(working copy)
@@ -716,6 +716,68 @@
 		$this->assertEquals( $control, $result_control );
 		$this->assertEquals( $control_id, $result_control->id );
 	}
+
+
+	/**
+	 * Testing the return values both with and without filter.
+	 *
+	 * @ticket 31195
+	 */
+	function test_get_previewable_devices() {
+
+		// Setup the instance.
+		$manager = new WP_Customize_Manager();
+
+		// The default devices list.
+		$default_devices = array(
+			'desktop' => array(
+				'label'   => __( 'Enter desktop preview mode' ),
+				'default' => true,
+			),
+			'tablet'  => array(
+				'label' => __( 'Enter tablet preview mode' ),
+			),
+			'mobile'  => array(
+				'label' => __( 'Enter mobile preview mode' ),
+			),
+		);
+
+		// Control test.
+		$devices = $manager->get_previewable_devices();
+		$this->assertSame( $default_devices, $devices );
+
+		// Adding the filter.
+		add_filter( 'customize_previewable_devices', array( $this, 'filter_customize_previewable_devices' ) );
+		$devices = $manager->get_previewable_devices();
+		$this->assertSame( $this->filtered_device_list(), $devices );
+
+		// Clean up.
+		remove_filter( 'customize_previewable_devices', array( $this, 'filter_customize_previewable_devices' ) );
+	}
+
+	/**
+	 * Helper method for test_get_previewable_devices
+	 * @return array
+	 */
+	function filtered_device_list() {
+		return array(
+			'device1' => array(
+				'label' => __( ' Enter device1 preview mode' ),
+				'default' => true,
+			),
+		);
+	}
+
+	/**
+	 * Callback for the customize_previewable_devices filter.
+	 *
+	 * @param array $devices The list of devices.
+	 *
+	 * @return array
+	 */
+	function filter_customize_previewable_devices( $devices ) {
+		return $this->filtered_device_list();
+	}
 }
 
 require_once ABSPATH . WPINC . '/class-wp-customize-setting.php';
