Before starting this tutorial, why create a video widget when there is already an Elementor video widget?
Because the default Elementor video widget loads the video frame, that is bad for page speed but it is to give you many controls like the autoplay, suggested videos, player control, etc…
In this tutorial, I will show you how to create a video widget that only loads the video thumbnail as you can see on the homepage of this site, this will make you win a lot of speed especially if you have many videos on the same page.
Let’s begin!

Step 1 – Call the Widget

The first step is to call the Elementor video widget we will create. I assume that you use a child theme but you can, of course, create a new plugin if you prefer.

Add the following code in the functions.php file of your child theme:

class OceanWP_Child_Theme {

	/**
	 * Main Theme Class Constructor
	 */
	public function __construct() {

		// Register the video widget
		add_action( 'elementor/widgets/widgets_registered', array( 'OceanWP_Child_Theme', 'widgets_registered' ) );

		// Load the video widget script
		add_action( 'elementor/frontend/after_register_scripts', array( 'OceanWP_Child_Theme', 'register_scripts' ) );

	} // End constructor

	// Register the video widget
	public static function widgets_registered() {

		// We check if the Elementor plugin has been installed / activated.
		if ( defined( 'ELEMENTOR_PATH' ) && class_exists( 'Elementor\Widget_Base' ) ) {
			require_once( get_stylesheet_directory() .'/widgets/video.php' );
		}

	}

	// Load the video widget script
	public static function register_scripts() {

	    // Register video script
		wp_register_script( 'owp-video', get_stylesheet_directory_uri() .'/js/video.js', [ 'jquery' ], 1.0, true );

	}

}
new OceanWP_Child_Theme;

The first function calls the video widget and the second function is to call the JS script that we need for this widget.


Step 2 – Widget Creation

In this second step, we will create the Elementor widget.
Create a widgets folder, this way you will be able to add other Elementor widgets to have a clean child theme.
Then, create a video.php file in this folder, open this file in your text editor and add this code:

<?php
namespace Elementor;

// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

class OWP_Widget_Video extends Widget_Base {

	public function get_name() {
		return 'owp-video';
	}

	public function get_title() {
		return 'Video Widget';
	}

	public function get_icon() {
		return 'eicon-youtube';
	}

	public function get_script_depends() {
		return [ 'owp-video' ];
	}

	protected function _register_controls() {

		$this->start_controls_section(
			'section_video',
			[
				'label' => 'Video',
			]
		);

		$this->add_control(
			'video_id',
			[
				'label' => 'Video ID',
				'type' => Controls_Manager::TEXT,
			]
		);

		$this->end_controls_section();

	}

	protected function render() {
		$id = $this->get_settings( 'video_id' ); ?>

		<div class="owp-fit-aspect-ratio">
			<div class="owp-youtube-player" data-id="<?php echo esc_attr( $id ); ?>">
				<div class="owp-play"><i class="eicon-play"></i></div>
			</div>
		</div>

	<?php
	}

	protected function _content_template() {}

}

Plugin::instance()->widgets_manager->register_widget_type( new OWP_Widget_Video() );

You can see that I use only one option to get the video ID, I want to keep this widget very simple.
You can also see that I call the JS script at step 1 in the get_script_depends() function, this script will be only loaded when you will add this video widget on your page.


Step 3 – The JS Script

The JS code will do all the magic, it will take your video thumbnail from YouTube via the video ID you will put in the widget and will replace the thumbnail by an iframe when you will click on it.

Create a js folder in your child theme and create a video.js file inside this folder. Open this file in your text editor and add this JS code:

document.addEventListener( 'DOMContentLoaded', function() {
    var i,
        video = document.getElementsByClassName( 'owp-youtube-player' );
        
    for (i = 0; i < video.length; i++) {

        // We get the thumbnail image from the YouTube ID
        video[i].style.backgroundImage = 'url(//i.ytimg.com/vi/' + video[i].dataset.id + '/maxresdefault.jpg)';

        video[i].onclick = function() {
            var iframe  = document.createElement( 'iframe' ),
                embed   = 'https://www.youtube.com/embed/ID?autoplay=1&rel=0&controls=0&showinfo=0&mute=0&wmode=opaque';
            iframe.setAttribute( 'src', embed.replace( 'ID', this.dataset.id ) );
            iframe.setAttribute( 'frameborder', '0' );
            iframe.setAttribute( 'allowfullscreen', '1' );
            this.parentNode.replaceChild( iframe, this );
        }

    }

} );

This is a very simple code to display the video when you click on its thumbnail.
You can add or change some controls at line 12.


Step 4 – The CSS Code

Right now, there is no way to load a CSS file only when an Elementor widget is used as a JS script, so add directly this CSS code in the style.css file of the child theme:

.owp-fit-aspect-ratio {
	position: relative;
	height: 0;
	padding-bottom: 56.25%;
}

.owp-fit-aspect-ratio iframe {
	position: absolute;
	top: 0;
	left: 0;
	height: 100%;
	width: 100%;
	border: 0;
	line-height: 1;
}

.owp-youtube-player {
	position: absolute;
	top: 0;
	left: 0;
	width: 100%;
	height: 100%;
	background-size: cover;
	background-position: 50%;
}

.owp-youtube-player {
	cursor: pointer;
	text-align: center;
}

.owp-youtube-player img {
	display: block;
	width: 100%;
}

.owp-play {
	position: absolute;
	top: 50%;
	left: 50%;
	-webkit-transform: translateX(-50%) translateY(-50%);
	-ms-transform: translateX(-50%) translateY(-50%);
	transform: translateX(-50%) translateY(-50%);
}

.owp-play i {
	font-size: 120px;
	color: #fff;
	opacity: 0.8;
	text-shadow: 1px 0 6px rgba(0, 0, 0, 0.3);
	-webkit-transition: all .5s;
	-o-transition: all .5s;
	transition: all .5s;
}

.owp-youtube-player:hover .owp-play i {
	opacity: 1;
}

Step 5 – Add your Video ID in the Widget

The final step is to copy/paste your video ID into our video widget. To get the ID, it is very simple, open your YouTube video in your browser, for example: https://www.youtube.com/watch?v=jeZfDUWfbd8

The video ID of this link is what you see just after watch?v=, so jeZfDUWfbd8.

Now, open the Elementor editor, you will see a new video widget, add it to your page or post, and paste your video ID in the Video ID field.
Note: If you don’t find the widget, do a search for Video, you will see Video Widget, this is our widget.

That all! Now, go to the front-end of your site, you will see your video thumbnail and when you click on it, your video will appear.


Conclusion

You can see that it is a simple widget easy to create and much better than adding a YouTube embed code that directly load the video frame.
Tell me in the comments if you like this tutorial and if you want more tutorials like this.

Nicolas Lecocq

When I am not working on improving OceanWP or creating new extensions, it is possible that I write an article on the blog... or I watch Game Of Thrones :)

This Post Has 12 Comments

  1. Hello Nicolas,

    Great article! What if we are using a cache plugin like WP rocket?
    Since version 2.11 December 14, 2017, they have added a feature that also automatically replace Youtube video’s by clickable thumbnails. This seems very much “duplicate” function.
    Will this not conflict and run into issues? Or perhaps I don’t need your script when WP rocket is activated?
    Or is it better to disable this feature in WP rocket and use your script?

    From changelog version 2.11: https://wp-rocket.me/changelog/
    “Enhancement: As a new lazyload option, you can now replace Youtube videos by clickable thumbnails, which can help your loading time if you have a lot of videos on the same page”

    Thanks!

    1. Hello Fabio, glad that you like the article 🙂
      I saw this new feature in WP Rocket, I never tested it but I think this is the same thing so it is totally up to you 🙂
      For my part, I prefer to use my own widget to control everything (style, no title or description in the video, etc…).

  2. Amazing Nicolas, thank you. I will use this widget instead of Elementor’s.

  3. Hi Nicolas. As always, thanks for your continual optimization ideas, both within the theme code and externally as here.

  4. Ok nice. Is it possible to hide/delete the YouTube logo in right down corner?

    1. Hi, I don’t think it is possible, YouTube want to show that you watch their video 🙂

  5. Issue with your base theme when numbered list is used. Hope somebody has appraised you of the issue!
    On the other note ie. your work and contribution : Simply Splendid!

    1. Hello, thanks for the nice words 🙂
      Have you an example of the issue?

  6. Nicolas,

    How can we work the video widget like this by using the ‘Embed Code’ or ‘oEmbed URL’ or ‘Link’ Post options in ‘OceanWP Settings’ on a post?

    It would be great to be able to have a client simply fill out the content, and the video URL (paste it into the oEmbed URL and/or Link or something like that) and have that URL apply to this widget. I seem to see references to it in ACF’s documentation and the oEmbed documentation, but would it be possible to apply it to this custom widget?

    1. Hello, why do you want to use an embed code for this widget? You just need to add your video ID. With an embed code, the iframe will be loaded, this widget is specially built to not use the iframe.

Leave a Reply

29 Shares
Tweet
Share29
+1
Pin
[i]
[i]
[i]
[i]