Index: src/wp-admin/css/customize-controls.css
===================================================================
--- src/wp-admin/css/customize-controls.css	(revision 38866)
+++ src/wp-admin/css/customize-controls.css	(working copy)
@@ -583,6 +583,7 @@
 	display: block;
 	font-style: italic;
 	line-height: 18px;
+	margin-top: 0;
 	margin-bottom: 5px;
 }
 
Index: src/wp-content/themes/twentyfourteen/functions.php
===================================================================
--- src/wp-content/themes/twentyfourteen/functions.php	(revision 38866)
+++ src/wp-content/themes/twentyfourteen/functions.php	(working copy)
@@ -409,7 +409,7 @@
 		$classes[] = 'group-blog';
 	}
 
-	if ( get_header_image() ) {
+	if ( get_header_image() || function_exists( 'has_header_video' ) && has_header_video() ) {
 		$classes[] = 'header-image';
 	} elseif ( ! in_array( $GLOBALS['pagenow'], array( 'wp-activate.php', 'wp-signup.php' ) ) ) {
 		$classes[] = 'masthead-fixed';
Index: src/wp-content/themes/twentyfourteen/header.php
===================================================================
--- src/wp-content/themes/twentyfourteen/header.php	(revision 38866)
+++ src/wp-content/themes/twentyfourteen/header.php	(working copy)
@@ -32,7 +32,11 @@
 
 <body <?php body_class(); ?>>
 <div id="page" class="hfeed site">
-	<?php if ( get_header_image() ) : ?>
+	<?php if ( function_exists( 'has_header_video' ) && has_header_video() ) : ?>
+		<div id="site-header">
+			<?php the_header_video_tag(); ?>
+		</div>
+	<?php elseif ( get_header_image() ) : ?>
 	<div id="site-header">
 		<a href="<?php echo esc_url( home_url( '/' ) ); ?>" rel="home">
 			<img src="<?php header_image(); ?>" width="<?php echo get_custom_header()->width; ?>" height="<?php echo get_custom_header()->height; ?>" alt="<?php echo esc_attr( get_bloginfo( 'name', 'display' ) ); ?>">
Index: src/wp-content/themes/twentyfourteen/inc/custom-header.php
===================================================================
--- src/wp-content/themes/twentyfourteen/inc/custom-header.php	(revision 38866)
+++ src/wp-content/themes/twentyfourteen/inc/custom-header.php	(working copy)
@@ -40,6 +40,7 @@
 		'width'                  => 1260,
 		'height'                 => 240,
 		'flex-height'            => true,
+		'video'                  => true,
 		'wp-head-callback'       => 'twentyfourteen_header_style',
 		'admin-head-callback'    => 'twentyfourteen_admin_header_style',
 		'admin-preview-callback' => 'twentyfourteen_admin_header_image',
Index: src/wp-content/themes/twentyfourteen/js/functions.js
===================================================================
--- src/wp-content/themes/twentyfourteen/js/functions.js	(revision 38866)
+++ src/wp-content/themes/twentyfourteen/js/functions.js	(working copy)
@@ -103,7 +103,7 @@
 
 			if ( body.is( '.header-image' ) ) {
 				toolbarOffset  = body.is( '.admin-bar' ) ? $( '#wpadminbar' ).height() : 0;
-				mastheadOffset = $( '#masthead' ).offset().top - toolbarOffset;
+				mastheadOffset = $( '#site-header' ).height() - toolbarOffset;
 
 				_window.on( 'scroll.twentyfourteen', function() {
 					if ( _window.scrollTop() > mastheadOffset && mastheadHeight < 49 ) {
@@ -112,6 +112,13 @@
 						body.removeClass( 'masthead-fixed' );
 					}
 				} );
+
+				// Update masthead offset after a selective refresh.
+				if ( 'undefined' !== typeof wp && wp.customize && wp.customize.selectiveRefresh ) {
+					wp.customize.selectiveRefresh.bind( 'partial-content-rendered', function( placement ) {
+						mastheadOffset = $( '#site-header' ).height() - toolbarOffset;
+					} );
+				}
 			}
 		}
 
Index: src/wp-content/themes/twentyfourteen/style.css
===================================================================
--- src/wp-content/themes/twentyfourteen/style.css	(revision 38866)
+++ src/wp-content/themes/twentyfourteen/style.css	(working copy)
@@ -88,6 +88,7 @@
 video {
 	display: inline-block;
 	max-width: 100%;
+	height: auto;
 }
 
 html {
@@ -608,6 +609,10 @@
 	max-width: 100%;
 }
 
+#wp-custom-header-video video {
+	margin-bottom: -8px;
+}
+
 p > embed,
 p > iframe,
 p > object,
Index: src/wp-content/themes/twentyseventeen/assets/css/ie8.css
===================================================================
--- src/wp-content/themes/twentyseventeen/assets/css/ie8.css	(revision 38868)
+++ src/wp-content/themes/twentyseventeen/assets/css/ie8.css	(working copy)
@@ -37,6 +37,12 @@
 
 /* Site Branding */
 
+.has-header-image .custom-header-image img,
+.has-header-image .custom-header-image video {
+	left: 0;
+	top: 0;
+}
+
 .site-title {
 	font-weight: bolder;
 }
Index: src/wp-content/themes/twentyseventeen/components/header/header-image.php
===================================================================
--- src/wp-content/themes/twentyseventeen/components/header/header-image.php	(revision 38868)
+++ src/wp-content/themes/twentyseventeen/components/header/header-image.php	(working copy)
@@ -14,12 +14,29 @@
 	$header_image = get_header_image();
 
 	// Check if Custom Header image has been added.
-	if ( ! empty( $header_image ) ) : ?>
+	if ( ! empty( $header_image ) ) :
 
-		<div class="custom-header-image" style="background-image: url(<?php echo esc_url( $header_image ); ?>)"></div>
-		<?php get_template_part( 'components/header/site', 'branding' ); ?>
+		// If yes, check if we're on the front page
+		if ( twentyseventeen_is_frontpage() ) : ?>
 
+			<?php // Output the full custom header - video and/or image fallback. ?>
+			<div class="custom-header-image">
+				<?php the_custom_header(); ?>
+			</div>
+			<?php get_template_part( 'components/header/site', 'branding' ); ?>
+
+		<?php else : ?>
+
+			<?php // If we're not on the front page, only output the header image. ?>
+			<div class="custom-header-image">
+				<img src="<?php echo esc_url( $header_image ); ?>">
+			</div>
+			<?php get_template_part( 'components/header/site', 'branding' ); ?>
+
+		<?php endif; ?>
+
 	<?php else : ?>
+
 		<?php // Otherwise, show a blank header. ?>
 		<div class="custom-header-simple">
 			<?php get_template_part( 'components/header/site', 'branding' ); ?>
Index: src/wp-content/themes/twentyseventeen/footer.php
===================================================================
--- src/wp-content/themes/twentyseventeen/footer.php	(revision 38868)
+++ src/wp-content/themes/twentyseventeen/footer.php	(working copy)
@@ -14,31 +14,32 @@
 
 ?>
 
-	</div><!-- #content -->
+		</div><!-- #content -->
 
-	<footer id="colophon" class="site-footer" role="contentinfo">
-		<div class="wrap">
-			<?php
-			get_template_part( 'components/footer/footer', 'widgets' );
+		<footer id="colophon" class="site-footer" role="contentinfo">
+			<div class="wrap">
+				<?php
+				get_template_part( 'components/footer/footer', 'widgets' );
 
-			if ( has_nav_menu( 'social' ) ) : ?>
-				<nav class="social-navigation" role="navigation" aria-label="<?php _e( 'Footer Social Links Menu', 'twentyseventeen' ); ?>">
-					<?php
-						wp_nav_menu( array(
-							'theme_location' => 'social',
-							'menu_class'     => 'social-links-menu',
-							'depth'          => 1,
-							'link_before'    => '<span class="screen-reader-text">',
-							'link_after'     => '</span>' . twentyseventeen_get_svg( array( 'icon' => 'chain' ) ),
-						) );
-					?>
-				</nav><!-- .social-navigation -->
-			<?php endif;
+				if ( has_nav_menu( 'social' ) ) : ?>
+					<nav class="social-navigation" role="navigation" aria-label="<?php _e( 'Footer Social Links Menu', 'twentyseventeen' ); ?>">
+						<?php
+							wp_nav_menu( array(
+								'theme_location' => 'social',
+								'menu_class'     => 'social-links-menu',
+								'depth'          => 1,
+								'link_before'    => '<span class="screen-reader-text">',
+								'link_after'     => '</span>' . twentyseventeen_get_svg( array( 'icon' => 'chain' ) ),
+							) );
+						?>
+					</nav><!-- .social-navigation -->
+				<?php endif;
 
-			get_template_part( 'components/footer/site', 'info' );
-			?>
-		</div><!-- .wrap -->
-	</footer><!-- #colophon -->
+				get_template_part( 'components/footer/site', 'info' );
+				?>
+			</div><!-- .wrap -->
+		</footer><!-- #colophon -->
+	</div><!-- .site-content-contain -->
 </div><!-- #page -->
 <?php wp_footer(); ?>
 
Index: src/wp-content/themes/twentyseventeen/header.php
===================================================================
--- src/wp-content/themes/twentyseventeen/header.php	(revision 38868)
+++ src/wp-content/themes/twentyseventeen/header.php	(working copy)
@@ -49,4 +49,5 @@
 	endif;
 	?>
 
-	<div id="content" class="site-content">
+	<div class="site-content-contain">
+		<div id="content" class="site-content">
Index: src/wp-content/themes/twentyseventeen/inc/custom-header.php
===================================================================
--- src/wp-content/themes/twentyseventeen/inc/custom-header.php	(revision 38868)
+++ src/wp-content/themes/twentyseventeen/inc/custom-header.php	(working copy)
@@ -39,6 +39,7 @@
 		'width'              => 2000,
 		'height'             => 1200,
 		'flex-height'        => true,
+		'video'              => true,
 		'wp-head-callback'   => 'twentyseventeen_header_style',
 	) ) );
 
Index: src/wp-content/themes/twentyseventeen/style.css
===================================================================
--- src/wp-content/themes/twentyseventeen/style.css	(revision 38868)
+++ src/wp-content/themes/twentyseventeen/style.css	(working copy)
@@ -1287,6 +1287,7 @@
 	border-top: 1px solid #eee;
 	font-size: 16px;
 	font-size: 1rem;
+	position: relative;
 }
 
 .navigation-top .wrap {
@@ -1528,8 +1529,10 @@
 
 .site-branding {
 	padding: 1em 0;
+	position: relative;
 	-webkit-transition: margin-bottom 0.2s;
 	transition: margin-bottom 0.2s;
+	z-index: 3;
 }
 
 .site-branding a {
@@ -1622,15 +1625,13 @@
 }
 
 .custom-header-image {
-	background-position: center center;
-	background-repeat: no-repeat;
-	-webkit-background-size: cover;
-	background-size: cover;
 	bottom: 0;
 	left: 0;
+	overflow: hidden;
 	position: absolute;
 	right: 0;
 	top: 0;
+	width: 100%;
 }
 
 .custom-header-image:before {
@@ -1646,12 +1647,36 @@
 	left: 0;
 	position: absolute;
 	right: 0;
+	z-index: 2;
 }
 
-.has-header-image:not(.twentyseventeen-front-page):not(.home) .custom-header-image {
-	background-position: center bottom;
+.has-header-image .custom-header-image img,
+.has-header-image .custom-header-image video {
+	position: fixed;
+	height: auto;
+	left: 50%;
+	max-width: 1000%;
+	min-height: 100%;
+	min-width: 100%;
+	min-width: 100vw; /* vw prevents 1px gap on left that 100% has */
+	width: auto;
+	top: 50%;
+	-ms-transform: translateX(-50%) translateY(-50%);
+	-moz-transform: translateX(-50%) translateY(-50%);
+	-webkit-transform: translateX(-50%) translateY(-50%);
+	transform: translateX(-50%) translateY(-50%);
 }
 
+.has-header-image:not(.twentyseventeen-front-page):not(.home) .custom-header-image img {
+	bottom: 0;
+	position: absolute;
+	top: auto;
+	-ms-transform: translateX(-50%) translateY(0);
+	-moz-transform: translateX(-50%) translateY(0);
+	-webkit-transform: translateX(-50%) translateY(0);
+	transform: translateX(-50%) translateY(0);
+}
+
 body:not(.has-header-image) .custom-header-image {
 	padding: 5% 0;
 }
@@ -1749,6 +1774,11 @@
 ## Regular Content
 --------------------------------------------------------------*/
 
+.site-content-contain {
+	background-color: #fff;
+	position: relative;
+}
+
 .site-content {
 	padding: 2.5em 0 0;
 }
@@ -2614,7 +2644,8 @@
 # Media
 --------------------------------------------------------------*/
 
-img {
+img,
+video {
 	height: auto; /* Make sure images are scaled correctly. */
 	max-width: 100%; /* Adhere to container width. */
 }
@@ -3258,7 +3289,6 @@
 
 	.has-header-image.twentyseventeen-front-page .custom-header,
 	.has-header-image.home.blog .custom-header {
-		display: block;
 		min-height: 0;
 	}
 
@@ -3267,6 +3297,12 @@
 		position: relative;
 	}
 
+	.twentyseventeen-front-page.has-header-image .custom-header-image,
+	.home.blog.has-header-image .custom-header-image {
+		height: 0;
+		position: relative;
+	}
+
 	.has-header-image:not(.twentyseventeen-front-page):not(.home) .custom-header-image {
 		bottom: 0;
 		height: auto;
@@ -3276,13 +3312,6 @@
 		top: 0;
 	}
 
-	.twentyseventeen-front-page.has-header-image .custom-header-image,
-	.home.blog.has-header-image .custom-header-image {
-		height: 0;
-		padding-top: 66%;
-		position: relative;
-	}
-
 	.custom-logo-link {
 		padding-right: 2em;
 	}
@@ -3554,7 +3583,8 @@
 		height: 1200px;
 		height: 100vh;
 		max-height: 100%;
-		padding: 10% 0;
+		overflow: hidden;
+		/* padding: 10% 0; */
 	}
 
 	.twentyseventeen-front-page.has-header-image .custom-header-image:before,
@@ -3901,11 +3931,6 @@
 
 @media screen and ( min-width: 55em ) {
 
-	.twentyseventeen-front-page.has-header-image .custom-header-image,
-	.home.blog.has-header-image .custom-header-image {
-		background-attachment: fixed;
-	}
-
 	.panel-image {
 		background-attachment: fixed;
 	}
Index: src/wp-includes/class-wp-customize-manager.php
===================================================================
--- src/wp-includes/class-wp-customize-manager.php	(revision 38866)
+++ src/wp-includes/class-wp-customize-manager.php	(working copy)
@@ -3223,12 +3223,46 @@
 
 		/* Custom Header */
 
+		if ( current_theme_supports( 'custom-header', 'video' ) ) {
+			$title = __( 'Header Visuals' );
+			$description = __( 'If you add a video, the image will be used as a fallback while the video loads.' );
+			$width = absint( get_theme_support( 'custom-header', 'width' ) );
+			$height = absint( get_theme_support( 'custom-header', 'height' ) );
+			if ( $width && $height ) {
+				/* translators: %s: header size in pixels */
+				$control_description = sprintf( __( 'Upload your video in <code>.mp4</code> format and minimize its file size for best results. Your theme recommends dimensions of %s pixels.' ),
+					sprintf( '<strong>%s &times; %s</strong>', $width, $height )
+				);
+			} elseif ( $width ) {
+				/* translators: %s: header width in pixels */
+				$control_description = sprintf( __( 'Upload your video in <code>.mp4</code> format and minimize its file size for best results. Your theme recommends a width of %s pixels.' ),
+					sprintf( '<strong>%s</strong>', $width )
+				);
+			} else {
+				/* translators: %s: header height in pixels */
+				$control_description = sprintf( __( 'Upload your video in <code>.mp4</code> format and minimize its file size for best results. Your theme recommends a height of %s pixels.' ),
+					sprintf( '<strong>%s</strong>', $height )
+				);
+			}
+		} else {
+			$title = __( 'Header Image' );
+			$description = '';
+			$control_description = '';
+		}
+
 		$this->add_section( 'header_image', array(
-			'title'          => __( 'Header Image' ),
+			'title'          => $title,
+			'description'    => $description,
 			'theme_supports' => 'custom-header',
 			'priority'       => 60,
 		) );
 
+		$this->add_setting( 'header_video', array(
+			'theme_supports'    => array( 'custom-header', 'video' ),
+			'transport'         => 'postMessage',
+			'validate_callback' => array( $this, '_validate_header_video' ),
+		) );
+
 		$this->add_setting( new WP_Customize_Filter_Setting( $this, 'header_image', array(
 			'default'        => get_theme_support( 'custom-header', 'default-image' ),
 			'theme_supports' => 'custom-header',
@@ -3239,8 +3273,22 @@
 			'theme_supports' => 'custom-header',
 		) ) );
 
+		$this->add_control( new WP_Customize_Media_Control( $this, 'header_video', array(
+			'theme_supports' => array( 'custom-header', 'video' ),
+			'label'          => __( 'Header Video' ),
+			'description'    => $control_description,
+			'section'        => 'header_image',
+			'mime_type'      => 'video',
+		) ) );
+
 		$this->add_control( new WP_Customize_Header_Image_Control( $this ) );
 
+		$this->selective_refresh->add_partial( 'header_video', array(
+			'selector' => '#wp-custom-header-video',
+			'render_callback' => 'get_header_video_tag',
+			'settings' => array( 'header_video', 'header_image' ), // The image is used as a video fallback here.
+		) );
+
 		/* Custom Background */
 
 		$this->add_section( 'background_image', array(
@@ -3595,6 +3643,27 @@
 	}
 
 	/**
+	 * Callback for validating the header_video value.
+	 *
+	 * Ensures that the selected video is less than 8MB and provides an error message.
+	 *
+	 * @since 4.7.0
+	 *
+	 * @param string $color
+	 * @return mixed
+	 */
+	public function _validate_header_video( $validity, $value ) {
+		$video = get_attached_file( absint( $value ) );
+		if ( $video ) {
+			$size = filesize( $video );
+			if ( 8 < $size / pow( 1024, 2 ) ) { // Check whether the size is larger than 8MB.
+				$validity->add( 'size_too_large', __( 'This video file is too large to use as a header video. Try a shorter video or optimize the compression settings and re-upload.' ) );
+			}
+		}
+		return $validity;
+	}
+
+	/**
 	 * Callback for rendering the custom logo, used in the custom_logo partial.
 	 *
 	 * This method exists because the partial object and context data are passed
Index: src/wp-includes/customize/class-wp-customize-header-image-control.php
===================================================================
--- src/wp-includes/customize/class-wp-customize-header-image-control.php	(revision 38866)
+++ src/wp-includes/customize/class-wp-customize-header-image-control.php	(working copy)
@@ -166,9 +166,14 @@
 		$height = absint( get_theme_support( 'custom-header', 'height' ) );
 		?>
 		<div class="customize-control-content">
-			<p class="customizer-section-intro">
+			<?php if ( current_theme_supports( 'custom-header', 'video' ) ) {
+				echo '<span class="customize-control-title">' . $this->label . '</span>';
+			} ?>
+			<p class="customizer-section-intro customize-control-description">
 				<?php
-				if ( $width && $height ) {
+				if ( current_theme_supports( 'custom-header', 'video' ) ) {
+					_e( 'While you can crop images to your liking after clicking <strong>Add new image</strong>, we recommend matching the size of your video.' );
+				} elseif ( $width && $height ) {
 					/* translators: %s: header size in pixels */
 					printf( __( 'While you can crop images to your liking after clicking <strong>Add new image</strong>, your theme recommends a header size of %s pixels.' ),
 						sprintf( '<strong>%s &times; %s</strong>', $width, $height )
Index: src/wp-includes/theme.php
===================================================================
--- src/wp-includes/theme.php	(revision 38866)
+++ src/wp-includes/theme.php	(working copy)
@@ -1264,6 +1264,7 @@
 		'thumbnail_url' => '',
 		'width'         => get_theme_support( 'custom-header', 'width' ),
 		'height'        => get_theme_support( 'custom-header', 'height' ),
+		'video'         => get_theme_support( 'custom-header', 'video' ),
 	);
 	return (object) wp_parse_args( $data, $default );
 }
@@ -1311,6 +1312,152 @@
 }
 
 /**
+ * Check whether a header video is set or not.
+ *
+ * @since 4.7.0
+ *
+ * @see get_header_video_url()
+ *
+ * @return bool Whether a header video is set or not.
+ */
+function has_header_video() {
+	return (bool) get_header_video_url();
+}
+
+/* Retrieve header video URL for custom header.
+*
+* @since 4.7.0
+*
+* @return string|false
+*/
+function get_header_video_url() {
+	$id = absint( get_theme_mod( 'header_video' ) );
+
+	if ( ! $id ) {
+		return false;
+	}
+
+	if ( $id ) {
+		// We have an attachment ID, need the full URL
+		$url = wp_get_attachment_url( $id );
+	}
+
+	return esc_url_raw( set_url_scheme( $url ) );
+}
+
+/**
+ * Create video tag markup for a custom header video.
+ *
+ * @since 4.7.0
+ *
+ * @param array $attr Optional. Additional attributes for the image tag. Can be used
+ *                              to override the default attributes. Default empty.
+ * @return string HTML image element markup or empty string on failure.
+ */
+function get_header_video_tag( $attr = array() ) {
+	$header = get_custom_header();
+	$video = get_header_video_url();
+	$image = get_header_image();
+
+	if ( empty( $video ) ) {
+		if ( is_customize_preview() ) { // If there was a video an it was removed, fall back to an image.
+			if ( ! empty( $image ) ) {
+				return get_header_image_tag();
+			}
+		}
+		return '';
+	}
+
+	$width = absint( $header->width );
+	$height = absint( $header->height );
+
+	$attr = wp_parse_args(
+		$attr,
+		array(
+			'src' => get_header_video_url(),
+			'width' => $width,
+			'height' => $height,
+			'controls' => '',
+			'autoplay' => '',
+			'loop' => '',
+			'muted' => '',
+		)
+	);
+
+	// Use the header image as poster attribute and video fallback.
+	if ( ! empty( $image ) ) {
+		$attr['poster'] = $header->url;
+		$content = get_header_image_tag();
+	} else {
+		$content = __( 'Your browser cannot play this video.' );
+	}
+
+	$attr = array_map( 'esc_attr', $attr );
+	$html = '<video';
+
+	foreach ( $attr as $name => $value ) {
+		$html .= ' ' . $name . '="' . $value . '"';
+	}
+
+	$html .= '>' . $content . '</video>';
+
+	/**
+	 * Filters the markup of header videos.
+	 *
+	 * @since 4.7.0
+	 *
+	 * @param string $html   The HTML image tag markup being filtered.
+	 * @param object $header The custom header object returned by 'get_custom_header()'.
+	 * @param array  $attr   Array of the attributes for the image tag.
+	 */
+	return apply_filters( 'get_header_video_tag', $html, $header, $attr );
+}
+
+/**
+ * Display the video markup for a custom header video.
+ *
+ * @since 4.7.0
+ *
+ * @param array $attr Optional. Attributes for the image markup. Default empty.
+ */
+function the_header_video_tag( $attr = array() ) {
+	echo '<div id="wp-custom-header-video">' . get_header_video_tag( $attr ) . '</div>';
+}
+
+/**
+ * Display header video URL.
+ *
+ * @since 4.7.0
+ */
+function the_header_video_url() {
+	$video = get_header_video_url();
+	if ( $video ) {
+		echo esc_url( $video );
+	}
+}
+
+/**
+ * Display the video and image markup for a custom header.
+ *
+ * @since 4.7.0
+ */
+function the_custom_header() {
+	$video = get_header_video_url();
+	$image = get_header_image();
+
+	if ( ! empty( $video ) ) {
+		the_header_video_tag();
+	} elseif ( is_customize_preview() ) {
+		echo '<div id="wp-custom-header-video"></div>';
+		if ( ! empty( $image ) ) {
+			the_header_image_tag();
+		}
+	} elseif ( ! empty( $image ) ) {
+		the_header_image_tag();
+	}
+}
+
+/**
  * Retrieve background image for custom background.
  *
  * @since 3.0.0
@@ -1706,6 +1853,7 @@
 				'wp-head-callback' => '',
 				'admin-head-callback' => '',
 				'admin-preview-callback' => '',
+				'video' => false,
 			);
 
 			$jit = isset( $args[0]['__jit'] );
