Use Video Embeds in Hugo Theme
Table of Contents
In this article, I will show how to handle video embedding when creating content for a Hugo-based website or enhancing a Hugo theme; it continues the series “Hugo Theme Recipes”.
With the proliferation of various video-sharing platforms such as YouTube, Vimeo , Bilibili, etc., the ability to post videos or include them in articles has become a necessity for any blog or website. This can be easily achieved if you plan to use videos from YouTube and Vimeo only, as Hugo includes built-in youtube and vimeo shortcodes by default.
Built-in Shortcodes
For example, to embed a responsive video player to display a YouTube video with the
URL https://www.youtube.com/watch?v=qtIqKaDlqXo, you simply need to
place {{< youtube qtIqKaDlqXo >}}
within the article’s markdown, where the qtIqKaDlqXo
value
is the video’s ID. To test the youtube
shortcode, I created
a test article on
the Bilberry Sandbox website where you can see what the embedded video looks like.
Raw HTML iframe
So far, so good, but what would you do if you need to embed videos from video-sharing providers
other than YouTube and Vimeo. For example, let’s say you want to use a video hosted on Bilibili, one
of the major China’s video-on-demand platforms. Simply trying to place the following iframe
embed
will not work:
<iframe src="//player.bilibili.com/player.html?bvid=BV1jz4y1f7yo&page=1&high_quality=1&danmaku=0"
scrolling="no" border="0" frameborder="no" framespacing="0" allowfullscreen="true"></iframe>
Since v0.60.0, Hugo switched to the Goldmark markdown renderer, which by default omits all raw
HTML content embedded in the markdown. To make it work, you should add the following setting to
your config.toml
configuration file:
[markup]
[markup.goldmark]
[markup.goldmark.renderer]
unsafe = true
The unsafe = true
option may sound intimidating, but it doesn’t necessarily make your website
insecure. Perhaps the creators of Hugo meant that the practice of using raw HTML in markdown should
be considered unsafe. The Bilberry Sandbox, which helps me develop, test, and maintain the Bilberry
theme, has the raw HTML rendering enabled. To try out the Bilibili iframe
embed, I’ve created
another test post,
where I also added the iframe
from the above YouTube video for comparison.
As you can see from the first screenshot below, both video embeds are not displayed responsively, i.e.,
they do not fully fit into the width of the article. In contrast, a YouTube video in the second
screenshot, which is embedded via the youtube
shortcode, does fit the article’s width since
its iframe
element and its surrounding div
have the required inline CSS styling.
Custom Shortcodes
Additionally, before addressing the issue with responsiveness, we can encapsulate the iframe
embed
in a custom shortcode instead of using it as a raw HTML, i.e., create a parametrizable shortcode
similar to the youtube
shortcode provided by Hugo. Here is
the layouts/shortcodes/bilibili.html
shortcode file I added to the Bilberry Sandbox:
{{ $id := .Get 0 }}
<div>
<iframe
src="https://player.bilibili.com/player.html?bvid={{ $id }}&page=1&as_wide=1&high_quality=1&danmaku=0"
scrolling="no" framespacing="0" webkitallowfullscreen mozallowfullscreen allowfullscreen>
</iframe>
</div>
To display the above-mentioned Bilibili video in an article, you need to
put {{< bilibili BV1jz4y1f7yo >}}
within the article’s markdown, where the BV1jz4y1f7yo
value is the video’s ID. As you can see, the video embed in
the test article
is displayed the same way as the raw HTML iframe
embed. But when using the bilibili
shortcode,
you no longer need to apply the unsafe = true
setting in the configuration file.
Responsiveness
To fix the issue with responsiveness when using custom shortcodes, you should define an external CSS
styling for the div
element containing the iframe
. For example, in the Bilberry theme, this
styling is implemented using the SCSS syntax
as follows:
&.article {
.responsive-video {
position: relative;
/* 16:9 ratio*/
padding-bottom: 56.25%;
padding-top: 0px;
height: 0;
overflow: hidden;
iframe {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
border: 0;
}
}
}
Then to apply the above styling, you should set the div’s class attribute with
the responsive-video
value: <div class="responsive-video">
.
Enhanced YouTube Shortcode
When using Hugo’s built-in youtube
shortcode, it will render as follows:
<div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;">
<iframe src="https://www.youtube.com/embed/qtIqKaDlqXo"
style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;"
allowfullscreen="" title="YouTube Video"></iframe>
</div>
As you can see, the src
attribute of the iframe element is set
to https://www.youtube.com/embed/qtIqKaDlqXo
. With this source URL, YouTube will automatically use
its tracking cookie. Unfortunately, that can pose a problem since the people visiting your site
usually do not consent to this YouTube tracker. In 2020, YouTube introduced a new privacy-enhanced
video embed that you can use to create your improved no-cookie YouTube shortcode. Here is
the youtube-enhanced
shortcode, which I implemented in the Bilberry Sandbox:
{{ $id := .Get "id" | default (.Get 0) }}
{{ $start := .Get "start" | default 0 }}
{{ $title := .Get "title" | default "YouTube Video" }}
<div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;">
<iframe src="https://www.youtube-nocookie.com/embed/{{ $id }}?rel=0&start={{ $start }}"
style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;"
allowfullscreen="" title="{{ $title }}"></iframe>
</div>
I created the following content to test this custom shortcode. It can be used the same way as the original shortcode from Hugo:
# Providing only the video ID as an unnamed parameter
{{< youtube-enhanced qtIqKaDlqXo >}}
# Providing only the video ID as the named id parameter
{{< youtube-enhanced id="qtIqKaDlqXo" >}}
# Providing values for named id, title, and start parameters
{{< youtube-enhanced id="qtIqKaDlqXo" title="Hugo Introduction" start="120" >}}
If the title
parameter is omitted, it will default to the YouTube Video
value. If you want to
start playing a video from a specific point, provide the start
parameter, whose value should be in
seconds. In addition, the source URL for the video in question contains the rel
parameter, which
is set to 0
. This parameter determines whether the player should show related videos when the
playback of the initial video ends. If set to 0
, no related videos will be
shown. Here you can read more on other
supported YouTube player parameters. Also, you can externalize the inline CSS styling by moving it
into a separate either CSS, SCSS, or SASS file.
Conclusion
Because Hugo provides shortcodes for two of the most popular video-sharing providers, YouTube and
Vimeo, posting videos from them doesn’t require any extra effort. However, the provided youtube
shortcode lacks privacy, which can be easily addressed by implementing your custom YouTube
shortcode. If you want to publish a video from any other provider, then this can be achieved by
either using a raw HTML iframe
embed or encapsulating it in a custom shortcode. I also want to
point out that the presented solution for creating video embed shortcodes can be applied to audio
embedding.
Continue reading the series “Hugo Theme Recipes”: