Shopify themes, liquid, logos, and UX
Hi There,
I'm using Dawn and have a video as the featured media for a key product.
I'm struggling to autoplay this video & hide controls. I've tried updating product-media.liquid as shown below to add muted & autoplay tags, but no luck. The link in question is https://velvetiser.myshopify.com/products/velvetiser-starter-kit password VUSA23
Can anyone help me with this (for both desktop & mobile!)
Thanks in advance,
Ollie
<template> {%- case media.media_type -%} {%- when 'external_video' -%} {%- assign video_class = 'js-' | append: media.host -%} {%- if media.host == 'youtube' -%} {{ media | external_video_url: muted: true, autoplay: true, loop: loop, playlist: media.external_id | external_video_tag: class: video_class, loading: "lazy" }} {%- else -%} {{ media | external_video_url: muted: true, autoplay: true, loop: loop | external_video_tag: class: video_class, loading: "lazy" }} {%- endif -%} {%- when 'video' -%} {{ media | media_tag: image_size: "2048x", muted: true, autoplay: true, loop: loop, preload: "auto" }} {%- when 'model' -%} {{ media | media_tag: image_size: "2048x", muted: true, autoplay: true, loop: loop, preload: "auto" }} {%- endcase -%} </template>
Solved! Go to the solution
This is an accepted solution.
For anyone who is stumbling across this and looking for a solution, I ended up using an online converter to convert the video file to webp. This has the effect of making the video load as if it was an image and autoplaying in all browsers I've tested. You can add as many of these files to your products as you want. Works perfectly!
Search for mp4 to webp converter to convert your files 🙂
Hi @OllieTP,
You can try this code by following these steps:
Step 1: Go to Online Store->Theme->Edit code.
Step 2: Search file theme.liquid
Step 3: Paste the below code at bottom of the file -> Save
{% if template contains "product" %}
<script>
window.addEventListener('DOMContentLoaded',(event)=>{
document.querySelectorAll('.deferred-media__poster-button.motion-reduce')[0].click()
});
</script>
{% endif %}
Hope my solution works perfectly for you!
Best regards,
Victor | PageFly
Hey Victor,
Thanks very much for helping.
I like the solution, and it works on Desktop, but unfortunately the behaviour on mobile is different. The first click seems to 'select' the video, a further click is required to start playback but content remains hidden behind controls until a third click (not on the play button) to hide the controls.
Here's a pic, as behaviour on mobile device is different to responsive mode on desktop
.
Hi@OllieTP ,
I just checked your site on the mobile but I see the video is autoplay. let's confirm your feedback . Thanks
I think If I can have access store I will check it carefully. let me know your feedback. Thanks
Hey would you mind helping me out with the same issue? I'm trying to make the video autoplay on this product page and it works on desktop but does not seem to autoplay on mobile:
OBYO | Mohair Crewneck Sweater – O BY O STORE (5c46e7.myshopify.com)
Hey @PageFly-Victor i am having the same issue, in the product gallery my product video is unable to auto play i tried everything but nothing's working. Can you help me? I want the video to auto play in both desktop and mobile.
This is an accepted solution.
For anyone who is stumbling across this and looking for a solution, I ended up using an online converter to convert the video file to webp. This has the effect of making the video load as if it was an image and autoplaying in all browsers I've tested. You can add as many of these files to your products as you want. Works perfectly!
Search for mp4 to webp converter to convert your files 🙂
I found a slightly better solution that uses product video files instead of .webp which is basically the same as .gif - slow loading and not that pretty.
In my case, I plan to add a few videos here and there as first product media, with "Show second image on hover" working as well, if needed.
Theme is Dawn 9.0.0
1) Open "card-product.liquid" in Theme code editor. Locate line 52 and replace the two "if" statements that end right before <div class="card__content"> with the following:
{%- if card_product.featured_media -%}
<div class="card__media">
<div class="media media--transparent media--hover-effect">
{% comment %}theme-check-disable ImgLazyLoading{% endcomment %}
{% liquid
assign alternateMediaIsVideo = false
if card_product.featured_media.media_type == 'video'
assign alternateMediaIsVideo = true
endif
%}
{% unless alternateMediaIsVideo %}
<img
srcset="
{%- if card_product.featured_media.width >= 165 -%}{{ card_product.featured_media | image_url: width: 165 }} 165w,{%- endif -%}
{%- if card_product.featured_media.width >= 360 -%}{{ card_product.featured_media | image_url: width: 360 }} 360w,{%- endif -%}
{%- if card_product.featured_media.width >= 533 -%}{{ card_product.featured_media | image_url: width: 533 }} 533w,{%- endif -%}
{%- if card_product.featured_media.width >= 720 -%}{{ card_product.featured_media | image_url: width: 720 }} 720w,{%- endif -%}
{%- if card_product.featured_media.width >= 940 -%}{{ card_product.featured_media | image_url: width: 940 }} 940w,{%- endif -%}
{%- if card_product.featured_media.width >= 1066 -%}{{ card_product.featured_media | image_url: width: 1066 }} 1066w,{%- endif -%}
{{ card_product.featured_media | image_url }} {{ card_product.featured_media.width }}w
"
src="{{ card_product.featured_media | image_url: width: 533 }}"
sizes="(min-width: {{ settings.page_width }}px) {{ settings.page_width | minus: 130 | divided_by: 4 }}px, (min-width: 990px) calc((100vw - 130px) / 4), (min-width: 750px) calc((100vw - 120px) / 3), calc((100vw - 35px) / 2)"
alt="{{ card_product.featured_media.alt | escape }}"
class="motion-reduce"
{% unless lazy_load == false %}
loading="lazy"
{% endunless %}
width="{{ card_product.featured_media.width }}"
height="{{ card_product.featured_media.height }}"
>
{% else %}
{{
card_product.featured_media
| video_tag:
controls: false,
muted: true,
loop: true,
autoplay: true,
image_size: '1066x',
class: 'motion-reduce'
}}
{% endunless %}
{% comment %}theme-check-enable ImgLazyLoading{% endcomment %}
{%- if card_product.media[1] != null and show_secondary_image -%}
{% liquid
assign alternateMediaIsVideo = false
if card_product.media[1].media_type == 'video'
assign alternateMediaIsVideo = true
endif
%}
{% unless alternateMediaIsVideo %}
<img
srcset="
{%- if card_product.media[1].width >= 165 -%}{{ card_product.media[1] | image_url: width: 165 }} 165w,{%- endif -%}
{%- if card_product.media[1].width >= 360 -%}{{ card_product.media[1] | image_url: width: 360 }} 360w,{%- endif -%}
{%- if card_product.media[1].width >= 533 -%}{{ card_product.media[1] | image_url: width: 533 }} 533w,{%- endif -%}
{%- if card_product.media[1].width >= 720 -%}{{ card_product.media[1] | image_url: width: 720 }} 720w,{%- endif -%}
{%- if card_product.media[1].width >= 940 -%}{{ card_product.media[1] | image_url: width: 940 }} 940w,{%- endif -%}
{%- if card_product.media[1].width >= 1066 -%}{{ card_product.media[1] | image_url: width: 1066 }} 1066w,{%- endif -%}
{{ card_product.media[1] | image_url }} {{ card_product.media[1].width }}w
"
src="{{ card_product.media[1] | image_url: width: 533 }}"
sizes="(min-width: {{ settings.page_width }}px) {{ settings.page_width | minus: 130 | divided_by: 4 }}px, (min-width: 990px) calc((100vw - 130px) / 4), (min-width: 750px) calc((100vw - 120px) / 3), calc((100vw - 35px) / 2)"
alt=""
class="motion-reduce"
loading="lazy"
width="{{ card_product.media[1].width }}"
height="{{ card_product.media[1].height }}"
>
{% else %}
{{
card_product.media[1]
| video_tag:
controls: false,
muted: true,
loop: true,
autoplay: true,
image_size: '1066x',
class: 'motion-reduce'
}}
{% endunless %}
{%- endif -%}
</div>
</div>
{%- endif -%}
The added code pieces are without indentation for better overview.
2) In Theme customization, open Default Collection and add a new "Custom Liquid" section. Enter the following at the top code field (not the css field):
<style type="text/css">
.media.media--hover-effect > video + video,
.media.media--hover-effect > video + img,
.media.media--hover-effect > img + video {
opacity: 0;
}
.card__media .media video {
height: 100%;
object-fit: cover;
object-position: center center;
width: 100%;
}
@media screen and (min-width: 990px) {
.card .media.media--hover-effect > video:only-child,
.card-wrapper .media.media--hover-effect > video:only-child {
transition: transform var(--duration-long) ease;
}
.card:hover .media.media--hover-effect > video:first-child:only-child,
.card-wrapper:hover .media.media--hover-effect > video:first-child:only-child {
transform: scale(1.03);
}
.card-wrapper:hover
.media.media--hover-effect
> video:first-child:not(:only-child) {
opacity: 0;
}
.card-wrapper:hover .media.media--hover-effect > video + video,
.card-wrapper:hover .media.media--hover-effect > video + img,
.card-wrapper:hover .media.media--hover-effect > img + video {
opacity: 1;
transition: transform var(--duration-long) ease;
transform: scale(1.03);
}
}
</style>
Remember to set the "section padding" sliders to zero, and you're done.
There might be some redundant css that needs testing and transition animations need some tweaking. Other than that, different order variations of product images and videos are loading, autoplaying and looping.
Good luck!
Works great! Thank you so much.
This code works perfect. Actually the first code is enough, we dont have to create a custom liquid. Thank you again
This is awesome and works good. Thanks for posting this
Thanks for your work!
I made some changes based on your work that will work in the following way:
1. We can put the video in whatever location we want, it also doesn't matter where we put the images
2. What happens is we check if the first media item is an image, if not we search through the list of media items until we see an image and assign that to a local value
3. For the video we do something similair but we search through the media list until we find an item that is a video, we also assign that to a local value
4. We use these values to decide what needs to be displayed as "featured" item and as "hovered" item
5. I added some javascript to make sure the videos only play when you hover over the product and that it will reset every time in order to play from the start on each hover
This is the code in the card_product.liquid file
under the `assign ratio` section around line 28 we will add some new assigns. This block will look like this:
{%- liquid
assign ratio = 1
if featuredImage and media_aspect_ratio == 'portrait'
assign ratio = 0.8
elsif featuredImage and media_aspect_ratio == 'adapt'
assign ratio = featuredImage.aspect_ratio
endif
if ratio == 0 or ratio == null
assign ratio = 1
endif
assign featuredImage = featuredImage
if featuredImage.media_type != 'video'
for item in card_product.media
if item.media_type == 'image'
assign featuredImage = item
break
endif
endfor
endif
assign featuredVideo = nil
for item in card_product.media
if item.media_type == 'video'
assign featuredVideo = item
break
endif
endfor
-%}
now do a search and replace on the page by using ctrl + f
enter: card_product.featured_media
and for replace: featuredImage
then replace the code for the first div below the first {%- if featuredImage -%} you find (should be around line 72 after adding the above code)
so replace the entire div with the code below
<div class="card__media{% if image_shape and image_shape != 'default' %} shape--{{ image_shape }} color-{{ settings.card_color_scheme }} gradient{% endif %}">
<div class="media media--transparent media--hover-effect">
{% comment %}theme-check-disable ImgLazyLoading{% endcomment %}
<img
srcset="
{%- if featuredImage.width >= 165 -%}{{ featuredImage | image_url: width: 165 }} 165w,{%- endif -%}
{%- if featuredImage.width >= 360 -%}{{ featuredImage | image_url: width: 360 }} 360w,{%- endif -%}
{%- if featuredImage.width >= 533 -%}{{ featuredImage | image_url: width: 533 }} 533w,{%- endif -%}
{%- if featuredImage.width >= 720 -%}{{ featuredImage | image_url: width: 720 }} 720w,{%- endif -%}
{%- if featuredImage.width >= 940 -%}{{ featuredImage | image_url: width: 940 }} 940w,{%- endif -%}
{%- if featuredImage.width >= 1066 -%}{{ featuredImage | image_url: width: 1066 }} 1066w,{%- endif -%}
{{ featuredImage | image_url }} {{ featuredImage.width }}w
"
src="{{ featuredImage | image_url: width: 533 }}"
sizes="(min-width: {{ settings.page_width }}px) {{ settings.page_width | minus: 130 | divided_by: 4 }}px, (min-width: 990px) calc((100vw - 130px) / 4), (min-width: 750px) calc((100vw - 120px) / 3), calc((100vw - 35px) / 2)"
alt="{{ featuredImage.alt | escape }}"
class="motion-reduce"
{% unless lazy_load == false %}
loading="lazy"
{% endunless %}
width="{{ featuredImage.width }}"
height="{{ featuredImage.height }}"
>
{% comment %}theme-check-enable ImgLazyLoading{% endcomment %}
{%- if card_product.media[1] != null or featuredVideo and show_secondary_image -%}
{%- unless featuredVideo != nil -%}
<img
srcset="
{%- if card_product.media[1].width >= 165 -%}{{ card_product.media[1] | image_url: width: 165 }} 165w,{%- endif -%}
{%- if card_product.media[1].width >= 360 -%}{{ card_product.media[1] | image_url: width: 360 }} 360w,{%- endif -%}
{%- if card_product.media[1].width >= 533 -%}{{ card_product.media[1] | image_url: width: 533 }} 533w,{%- endif -%}
{%- if card_product.media[1].width >= 720 -%}{{ card_product.media[1] | image_url: width: 720 }} 720w,{%- endif -%}
{%- if card_product.media[1].width >= 940 -%}{{ card_product.media[1] | image_url: width: 940 }} 940w,{%- endif -%}
{%- if card_product.media[1].width >= 1066 -%}{{ card_product.media[1] | image_url: width: 1066 }} 1066w,{%- endif -%}
{{ card_product.media[1] | image_url }} {{ card_product.media[1].width }}w
"
src="{{ card_product.media[1] | image_url: width: 533 }}"
sizes="(min-width: {{ settings.page_width }}px) {{ settings.page_width | minus: 130 | divided_by: 4 }}px, (min-width: 990px) calc((100vw - 130px) / 4), (min-width: 750px) calc((100vw - 120px) / 3), calc((100vw - 35px) / 2)"
alt=""
class="motion-reduce"
loading="lazy"
width="{{ card_product.media[1].width }}"
height="{{ card_product.media[1].height }}"
>
{%- else -%}
{{
featuredVideo
| video_tag:
controls: false,
muted: true,
loop: true,
autoplay: false,
image_size: '1066x',
class: 'motion-reduce'
}}
{%- endunless -%}
{%- endif -%}
</div>
</div>
In order to make sure the autoplay works in the way as described in point 5 we add the following to the bottom of the page
<script>
document.addEventListener('DOMContentLoaded', function () {
document.querySelectorAll('.card').forEach((video) => {
video.addEventListener('mouseover', function() {
var playItem = this.querySelector('video');
playItem.currentTime = 0;
playItem.play();
});
video.addEventListener('mouseout', function() {
this.querySelector('video').pause();
});
});
});
</script>
The css part is the same as in LVC's answer
This is great & just what I was after. Thanks very much & super appreciation : )
Hello, I tried this, it works very well, but when I apply the code you gave in the first place, the products cannot be clicked. That is, only the product picture and video are visible on the home page, but I cannot open the product to see other product photos. Additionally, features such as product name, price, etc. were also deleted with this code. What is more accurate about this?
Recent Dawn theme updates have rendered my solution obsolete, and I'm currently trying this one by Pete Soc, that I found on the other post:
https://github.com/peterbrunton/shopify-gists/blob/main/product-card-rollover-video
This was such a simple and easy fix! Thanks @OllieTP for the pro tip... I used https://tinywow.com/video/to-webp to achieve the conversion from mp4 to webp but unfortunately, I noticed the file size doubled from 2mb to 4.15mb...
It does auto-play AND it shows the 2nd line image (our video webp) now upon desktop hover all without any code!
Thanks a ton @OllieTP for such incredible and EASY solution!!! I thought that webp is for static only. It took me several days to find so easy solution for this problem. Thank you so much! You are my hero! No need to mess with video and coding now.
This totally worked! Thanks so much!
Hi, How to upload webp video in the image banner /Video banner for home page?
This is by far the easiest solution!! Thanks so much, I had no idea WebP preserves motion. I think the video solution with code is valuable for some use cases, but the WebP route worked perfectly for what I needed – higher quality and about half the size of my optimized gifs. 🙂
Starting a B2B store is a big undertaking that requires careful planning and execution. W...
By JasonH Sep 23, 2024By investing 30 minutes of your time, you can unlock the potential for increased sales,...
By Jacqui Sep 11, 2024We appreciate the diverse ways you participate in and engage with the Shopify Communi...
By JasonH Sep 9, 2024