Responsive controls
One thing you’ll quickly notice is that Media Chrome is not responsive out of the box. This is by design, there are way too many permutations possible to provide one configuration for a responsive media player. However media themes will be introduced soon that can provide responsive behavior by default.
There are different techniques available to make your Media Chrome controls
responsive but we’ll keep it simple in this guide and make use of
ResizeObserver
and CSS classes.
Basic unresponsive layout
Section titled Basic unresponsive layoutLets create a basic layout for our Media Chrome player.
<style>
media-controller {
display: block;
aspect-ratio: 16 / 9;
}
video {
width: 100%;
}
</style>
<media-controller>
<video
playsinline
slot="media"
src="https://stream.mux.com/O6LdRc0112FEJXH00bGsN9Q31yu5EIVHTgjTKRkKtEq1k/high.mp4"
poster="https://image.mux.com/O6LdRc0112FEJXH00bGsN9Q31yu5EIVHTgjTKRkKtEq1k/thumbnail.jpg?time=56"
></video>
<media-control-bar>
<media-play-button></media-play-button>
<media-mute-button></media-mute-button>
<media-volume-range></media-volume-range>
<media-time-display></media-time-display>
<media-time-range></media-time-range>
<media-duration-display></media-duration-display>
<media-playback-rate-button></media-playback-rate-button>
<media-fullscreen-button></media-fullscreen-button>
</media-control-bar>
</media-controller>
That looks pretty good but the controls are static no matter the size of the player.
Lets change that, for this exercise we’ll make a big center play button when the player
width is smaller than 484px
and only show the timerange at the bottom of the player.
Observe player resizing
Section titled Observe player resizingSince we’re still waiting for
CSS Container Queries
to get wider adoption,
this will require ResizeObserver
to detect any size changes to the container of the player.
You might be tempted to use media queries for this but that solution will probably backfire because a media query listens to the browser viewport dimensions, not the player container dimensions.
<script>
const breakpoints = { xs: 396, sm: 484, md: 576, lg: 768, xl: 960 };
const resizeObserver = new ResizeObserver(function (entries) {
entries.forEach((entry) => {
const classNames = getBreakpoints(breakpoints, entry.contentRect);
console.log(classNames);
});
});
resizeObserver.observe(document.querySelector('media-controller'));
function getBreakpoints(breakpoints, rect) {
return Object.keys(breakpoints).filter((key) => {
return rect.width >= breakpoints[key];
});
}
</script>
This little snippet will output the defined breakpoints as class names whenever the width of the player is smaller than the defined breakpoint.
CSS classes & properties
Section titled CSS classes & propertiesNow it’s as simple as adding some CSS classes and CSS properties to hide and show controls based on the breakpoints.
<style>
media-controller {
display: block;
aspect-ratio: 16 / 9;
}
video {
width: 100%;
}
/* Hide most of the bottom controls on a tiny player. */
media-controller:not(.sm) .bottom :not(media-time-range) {
display: none;
}
/* Hide the big center play button on a larger player. */
media-controller.sm .center {
display: none;
}
</style>
<media-controller id="mc2">
<video
playsinline
slot="media"
src="https://stream.mux.com/O6LdRc0112FEJXH00bGsN9Q31yu5EIVHTgjTKRkKtEq1k/high.mp4"
poster="https://image.mux.com/O6LdRc0112FEJXH00bGsN9Q31yu5EIVHTgjTKRkKtEq1k/thumbnail.jpg?time=56"
></video>
<div class="center" slot="centered-chrome">
<media-play-button></media-play-button>
</div>
<media-control-bar class="bottom">
<media-play-button></media-play-button>
<media-mute-button></media-mute-button>
<media-volume-range></media-volume-range>
<media-time-display></media-time-display>
<media-time-range></media-time-range>
<media-duration-display></media-duration-display>
<media-playback-rate-button></media-playback-rate-button>
<media-fullscreen-button></media-fullscreen-button>
</media-control-bar>
</media-controller>
<script>
const breakpoints = { xs: 396, sm: 484, md: 576, lg: 768, xl: 960 };
const mc = document.querySelector('#mc2');
const resizeObserver = new ResizeObserver(function (entries) {
entries.forEach((entry) => {
const classNames = getBreakpoints(breakpoints, entry.contentRect);
entry.target.className = classNames.join(' ');
});
});
resizeObserver.observe(mc);
function getBreakpoints(breakpoints, rect) {
return Object.keys(breakpoints).filter((key) => {
return rect.width >= breakpoints[key];
});
}
</script>
Responsive Media Chrome player
Section titled Responsive Media Chrome playerTry changing the size of the player embed below to see if the controls show and hide like expected.