aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSam Potts <me@sampotts.me>2017-10-28 20:14:33 +1100
committerSam Potts <me@sampotts.me>2017-10-28 20:14:33 +1100
commit3d50936b47fdd691816843de962d5699c3c8f596 (patch)
tree1ec372b21d86bd54cc0e9e679e1ef37f68344b32 /src
parentdd9d5c8898bd5e58c6faec13d6213b8fe079446a (diff)
downloadplyr-3d50936b47fdd691816843de962d5699c3c8f596.tar.lz
plyr-3d50936b47fdd691816843de962d5699c3c8f596.tar.xz
plyr-3d50936b47fdd691816843de962d5699c3c8f596.zip
Split LESS into more granular files, Vimeo fixes
Diffstat (limited to 'src')
-rw-r--r--src/js/plyr.js169
-rw-r--r--src/less/base.less48
-rw-r--r--src/less/bundle.less29
-rw-r--r--src/less/components/badges.less11
-rw-r--r--src/less/components/buttons.less89
-rw-r--r--src/less/components/captions.less57
-rw-r--r--src/less/components/controls.less127
-rw-r--r--src/less/components/embed.less23
-rw-r--r--src/less/components/menus.less155
-rw-r--r--src/less/components/progress.less110
-rw-r--r--src/less/components/sliders.less140
-rw-r--r--src/less/components/times.less28
-rw-r--r--src/less/components/tooltips.less87
-rw-r--r--src/less/components/video.less12
-rw-r--r--src/less/components/volume.less30
-rw-r--r--src/less/lib/animation.less21
-rw-r--r--src/less/lib/mixins.less (renamed from src/less/mixins.less)4
-rw-r--r--src/less/plyr.less957
-rw-r--r--src/less/settings.less (renamed from src/less/variables.less)0
-rw-r--r--src/less/states/fullscreen.less31
-rw-r--r--src/less/utils/hidden.less33
21 files changed, 1138 insertions, 1023 deletions
diff --git a/src/js/plyr.js b/src/js/plyr.js
index 4fd7c397..3968162a 100644
--- a/src/js/plyr.js
+++ b/src/js/plyr.js
@@ -304,6 +304,7 @@
hideControls: 'plyr--hide-controls',
isIos: 'plyr--is-ios',
isTouch: 'plyr--is-touch',
+ uiSupported: 'plyr--full-ui',
menu: {
value: 'plyr__menu__value',
badge: 'plyr__badge',
@@ -468,54 +469,58 @@
name: name,
version: majorVersion,
isIE: isIE,
- isOldIE: isIE && majorVersion <= 9,
isFirefox: isFirefox,
isChrome: isChrome,
isSafari: isSafari,
isWebkit: 'WebkitAppearance' in document.documentElement.style,
isIPhone: /(iPhone|iPod)/gi.test(navigator.platform),
isIos: /(iPad|iPhone|iPod)/gi.test(navigator.platform),
+ isSupported: !(isIE && majorVersion <= 9),
};
},
// Check for support
// Basic functionality vs full UI
checkSupport: function(type, inline) {
- var basic = false;
- var full = false;
+ var api = false;
+ var ui = false;
var browser = utils.getBrowser();
var playsInline = browser.isIPhone && inline && support.inline;
switch (type) {
case 'video':
- basic = support.video;
- full = basic && !browser.isOldIE && (!browser.isIPhone || playsInline);
+ api = support.video;
+ ui = api && browser.isSupported && (!browser.isIPhone || playsInline);
break;
case 'audio':
- basic = support.audio;
- full = basic && !browser.isOldIE;
+ api = support.audio;
+ ui = api && browser.isSupported;
break;
case 'youtube':
- basic = support.video;
- full = basic && !browser.isOldIE && (!browser.isIPhone || playsInline);
+ api = true;
+ ui = api && browser.isSupported && (!browser.isIPhone || playsInline);
break;
case 'vimeo':
+ api = true;
+ ui = false;
+ break;
+
case 'soundcloud':
- basic = true;
- full = !browser.isOldIE && !browser.isIos;
+ api = true;
+ ui = browser.isSupported;
break;
default:
- basic = support.audio && support.video;
- full = basic && !browser.isOldIE;
+ api = support.audio && support.video;
+ ui = api && browser.isSupported;
}
return {
- basic: basic,
- full: full,
+ api: api,
+ ui: ui,
};
},
@@ -1371,7 +1376,7 @@
}
// Trap focus inside container
- function focusTrap() {
+ function trapFocus() {
var tabbables = getElements('input:not([disabled]), button:not([disabled])');
var first = tabbables[0];
var last = tabbables[tabbables.length - 1];
@@ -1455,9 +1460,14 @@
}
var styleSheet = player.elements.styleSheet.sheet;
- var percentage = (range.value / range.max) * 100;
+ var percentage = range.value / range.max * 100;
var selector = '#' + range.id + '::-webkit-slider-runnable-track';
- var styles = '{ background-image: linear-gradient(to right, currentColor ' + percentage + '%, transparent ' + percentage + '%) }';
+ var styles =
+ '{ background-image: linear-gradient(to right, currentColor ' +
+ percentage +
+ '%, transparent ' +
+ percentage +
+ '%) }';
var index = -1;
// Find old rule if it exists
@@ -1761,7 +1771,6 @@
}
// Play Pause button
- // TODO: This should be a toggle button really?
if (utils.inArray(player.config.controls, 'play')) {
controls.appendChild(createButton('play'));
controls.appendChild(createButton('pause'));
@@ -2369,7 +2378,7 @@
// Setup fullscreen
function setupFullscreen() {
- if (!player.supported.full || player.type === 'audio' || !player.config.fullscreen.enabled) {
+ if (!player.supported.ui || player.type === 'audio' || !player.config.fullscreen.enabled) {
return;
}
@@ -2390,12 +2399,17 @@
utils.toggleState(player.elements.buttons.fullscreen, false);
}
- // Setup focus trap
- focusTrap();
+ // Trap focus in container
+ trapFocus();
}
// Setup captions
function setupCaptions() {
+ // Requires UI support
+ if (!player.supported.ui) {
+ return;
+ }
+
// Set default language if not set
if (!utils.is.empty(player.storage.language)) {
player.captions.language = player.storage.language;
@@ -2531,6 +2545,10 @@
// Get current selected caption language
function getLanguage() {
+ if (!player.supported.ui) {
+ return null;
+ }
+
if (!support.textTracks || utils.is.empty(player.captions.tracks)) {
return player.config.i18n.none;
}
@@ -2563,6 +2581,11 @@
// Set the current caption
function setCaption(caption) {
+ // Requires UI
+ if (!player.supported.ui) {
+ return;
+ }
+
if (utils.is.htmlElement(player.elements.captions)) {
var content = utils.createElement('span');
@@ -2759,11 +2782,17 @@
}
// Toggle style hook
- function toggleStyleHook() {
+ function addStyleHook() {
utils.toggleClass(
player.elements.container,
player.config.selectors.container.replace('.', ''),
- player.supported.full
+ true
+ );
+
+ utils.toggleClass(
+ player.elements.container,
+ player.config.classNames.uiSupported,
+ player.supported.ui
);
}
@@ -2790,7 +2819,7 @@
}
// If there's a play button, set label
- if (player.supported.full) {
+ if (player.supported.ui) {
if (utils.is.htmlElement(player.elements.buttons.play)) {
player.elements.buttons.play.setAttribute('aria-label', label);
}
@@ -2865,24 +2894,24 @@
return;
}
- if (player.supported.full) {
- // Add type class
+ // Add type class
+ utils.toggleClass(
+ player.elements.container,
+ player.config.classNames.type.replace('{0}', player.type),
+ true
+ );
+
+ // Add video class for embeds
+ // This will require changes if audio embeds are added
+ if (utils.inArray(types.embed, player.type)) {
utils.toggleClass(
player.elements.container,
- player.config.classNames.type.replace('{0}', player.type),
+ player.config.classNames.type.replace('{0}', 'video'),
true
);
+ }
- // Add video class for embeds
- // This will require changes if audio embeds are added
- if (utils.inArray(types.embed, player.type)) {
- utils.toggleClass(
- player.elements.container,
- player.config.classNames.type.replace('{0}', 'video'),
- true
- );
- }
-
+ if (player.supported.ui) {
// Check for picture-in-picture support
utils.toggleClass(
player.elements.container,
@@ -3028,7 +3057,7 @@
// When embeds are ready
function embedReady() {
// Setup the UI and call ready if full support
- if (player.supported.full) {
+ if (player.supported.ui) {
setupInterface();
ready();
}
@@ -3045,7 +3074,7 @@
videoId: videoId,
playerVars: {
autoplay: player.config.autoplay ? 1 : 0, // Autoplay
- controls: player.supported.full ? 0 : 1, // Only show controls if not fully supported
+ controls: player.supported.ui ? 0 : 1, // Only show controls if not fully supported
rel: 0, // No related vids
showinfo: 0, // Hide info
iv_load_policy: 3, // Hide annotations
@@ -3120,7 +3149,7 @@
player.config.title = instance.getVideoData().title;
// Set the tabindex
- if (player.supported.full) {
+ if (player.supported.ui) {
player.media.setAttribute('tabindex', -1);
}
@@ -3300,7 +3329,7 @@
player.embed.on('loaded', function() {
// Fix keyboard focus issues
// https://github.com/sampotts/plyr/issues/317
- if (utils.is.htmlElement(player.embed.element) && player.supported.full) {
+ if (utils.is.htmlElement(player.embed.element) && player.supported.ui) {
player.embed.element.setAttribute('tabindex', -1);
}
});
@@ -3345,6 +3374,7 @@
}
// Soundcloud ready
+ // TODO: Document
function soundcloudReady() {
/* jshint validthis: true */
player.embed = window.SC.Widget(this);
@@ -3568,7 +3598,7 @@
// Update volume UI and storage
function updateVolume() {
// Update the <input type="range"> if present
- if (player.supported.full) {
+ if (player.supported.ui) {
var value = player.media.muted ? 0 : player.media.volume;
if (player.elements.inputs.volume) {
@@ -3585,7 +3615,7 @@
utils.toggleClass(player.elements.container, player.config.classNames.muted, player.media.muted);
// Update checkbox for mute state
- if (player.supported.full && player.elements.buttons.mute) {
+ if (player.supported.ui && player.elements.buttons.mute) {
utils.toggleState(player.elements.buttons.mute, player.media.muted);
}
}
@@ -3645,7 +3675,7 @@
// Update <progress> elements
function updateProgress(event) {
- if (!player.supported.full) {
+ if (!player.supported.ui) {
return;
}
@@ -3732,7 +3762,7 @@
// Show the duration on metadataloaded
function displayDuration() {
- if (!player.supported.full) {
+ if (!player.supported.ui) {
return;
}
@@ -3911,9 +3941,9 @@
utils.toggleClass(
player.elements.container,
player.config.classNames.captions.active,
- player.captions.enabled
+ player.supported.ui && player.captions.enabled
);
- toggleStyleHook();
+ addStyleHook();
// Set new sources for html5
if (utils.inArray(types.html5, player.type)) {
@@ -3937,7 +3967,7 @@
// If HTML5 or embed but not fully supported, setupInterface and call ready now
if (
utils.inArray(types.html5, player.type) ||
- (utils.inArray(types.embed, player.type) && !player.supported.full)
+ (utils.inArray(types.embed, player.type) && !player.supported.ui)
) {
// Setup interface
setupInterface();
@@ -4180,7 +4210,7 @@
// Delay the adding of classname until the focus has changed
// This event fires before the focusin event
- window.setTimeout(function () {
+ window.setTimeout(function() {
utils.toggleClass(utils.getFocusElement(), player.config.classNames.tabFocus, true);
}, 0);
});
@@ -4385,7 +4415,9 @@
// Handle user exiting fullscreen by escaping etc
if (support.fullscreen) {
- utils.on(document, fullscreen.eventType, function(event) { player.toggleFullscreen(event); });
+ utils.on(document, fullscreen.eventType, function(event) {
+ player.toggleFullscreen(event);
+ });
}
}
@@ -4427,7 +4459,7 @@
utils.on(player.media, 'waiting canplay seeked', checkLoading);
// Click video
- if (player.config.clickToPlay && player.type !== 'audio') {
+ if (player.supported.ui && player.config.clickToPlay && player.type !== 'audio') {
// Re-fetch the wrapper
var wrapper = getElement('.' + player.config.classNames.video);
@@ -4552,8 +4584,12 @@
// Setup the UI
function setupInterface() {
+ // Re-attach media element listeners
+ // TODO: Use event bubbling
+ mediaListeners();
+
// Don't setup interface if no support
- if (!player.supported.full) {
+ if (!player.supported.ui) {
warn('Basic support only', player.type);
// Remove controls
@@ -4574,7 +4610,7 @@
// Inject custom controls
injectControls();
- // Re-attach listeners
+ // Re-attach control listeners
listeners();
}
@@ -4583,9 +4619,6 @@
return;
}
- // Media element listeners
- mediaListeners();
-
// Remove native controls
toggleNativeControls();
@@ -4650,7 +4683,7 @@
// Bail if disabled or no basic support
// You may want to disable certain UAs etc
- if (!utils.checkSupport().basic) {
+ if (!utils.checkSupport().api) {
error('Setup failed: no support');
return;
}
@@ -4722,8 +4755,8 @@
// Check for support again but with type
player.supported = utils.checkSupport(player.type, player.config.inline);
- // If no native support, bail
- if (!player.supported.basic) {
+ // If no support for even API, bail
+ if (!player.supported.api) {
error('Setup failed: no support');
return;
}
@@ -4735,10 +4768,10 @@
player.elements.container = utils.wrap(media, utils.createElement('div'));
// Allow focus to be captured
- player.elements.container.setAttribute('tabindex', 0);
+ // player.elements.container.setAttribute('tabindex', 0);
// Add style hook
- toggleStyleHook();
+ addStyleHook();
// Debug info
log(player.browser.name + ' ' + player.browser.version);
@@ -4757,7 +4790,7 @@
// If embed but not fully supported, setupInterface (to avoid flash of controls) and call ready now
if (
utils.inArray(types.html5, player.type) ||
- (utils.inArray(types.embed, player.type) && !player.supported.full)
+ (utils.inArray(types.embed, player.type) && !player.supported.ui)
) {
// Setup UI
setupInterface();
@@ -5304,7 +5337,7 @@
var player = this;
// If there's no full support, or there's no caption toggle
- if (!player.supported.full || !player.elements.buttons.captions) {
+ if (!player.supported.ui || !player.elements.buttons.captions) {
return;
}
@@ -5406,7 +5439,11 @@
player.fullscreen.active = !player.fullscreen.active;
// Add class hook
- utils.toggleClass(player.elements.container, player.config.classNames.fullscreen.fallback, player.fullscreen.active);
+ utils.toggleClass(
+ player.elements.container,
+ player.config.classNames.fullscreen.fallback,
+ player.fullscreen.active
+ );
// Make sure we don't lose scroll position
if (player.fullscreen.active) {
@@ -5483,7 +5520,7 @@
var player = this;
// Don't hide if config says not to, it's audio, or not ready or loading
- if (!player.config.hideControls || player.type === 'audio') {
+ if (!player.supported.ui || !player.config.hideControls || player.type === 'audio') {
return;
}
diff --git a/src/less/base.less b/src/less/base.less
new file mode 100644
index 00000000..e41874a0
--- /dev/null
+++ b/src/less/base.less
@@ -0,0 +1,48 @@
+// --------------------------------------------------------------
+// Base styling
+// --------------------------------------------------------------
+
+// Base
+.plyr {
+ position: relative;
+ max-width: 100%;
+ min-width: 200px;
+ overflow: hidden;
+ font-family: @plyr-font-family;
+ font-weight: @plyr-font-weight-normal;
+ direction: ltr;
+ text-shadow: none;
+
+ // Media elements
+ video,
+ audio {
+ width: 100%;
+ height: auto;
+ vertical-align: middle;
+ border-radius: inherit;
+ }
+}
+
+// Full UI only
+.plyr--full-ui {
+ & when(@plyr-border-box = true) {
+ // border-box everything
+ // http://paulirish.com/2012/box-sizing-border-box-ftw/
+ &,
+ *,
+ *::after,
+ *::before {
+ box-sizing: border-box;
+ }
+ }
+
+ & when(@plyr-touch-action = true) {
+ // Fix 300ms delay
+ a,
+ button,
+ input,
+ label {
+ touch-action: manipulation;
+ }
+ }
+}
diff --git a/src/less/bundle.less b/src/less/bundle.less
new file mode 100644
index 00000000..bff7fdec
--- /dev/null
+++ b/src/less/bundle.less
@@ -0,0 +1,29 @@
+// ==========================================================================
+// Plyr styles
+// https://github.com/sampotts/plyr
+// TODO: Review use of BEM classnames
+// ==========================================================================
+
+@import 'settings';
+
+@import 'lib/animation';
+@import 'lib/mixins';
+
+@import 'base';
+
+@import 'components/badges';
+@import 'components/buttons';
+@import 'components/captions';
+@import 'components/controls';
+@import 'components/embed';
+@import 'components/menus';
+@import 'components/progress';
+@import 'components/sliders';
+@import 'components/times';
+@import 'components/tooltips';
+@import 'components/video';
+@import 'components/volume';
+
+@import 'states/fullscreen';
+
+@import 'utils/hidden';
diff --git a/src/less/components/badges.less b/src/less/components/badges.less
new file mode 100644
index 00000000..37ed2af4
--- /dev/null
+++ b/src/less/components/badges.less
@@ -0,0 +1,11 @@
+// --------------------------------------------------------------
+// Badges
+// --------------------------------------------------------------
+
+.plyr__badge {
+ padding: 1px 4px;
+ border-radius: 2px;
+ background: @plyr-menu-color;
+ color: @plyr-menu-bg;
+ font-size: @plyr-font-size-tiny;
+}
diff --git a/src/less/components/buttons.less b/src/less/components/buttons.less
new file mode 100644
index 00000000..3aa6da1a
--- /dev/null
+++ b/src/less/components/buttons.less
@@ -0,0 +1,89 @@
+.plyr__control {
+ position: relative;
+ display: inline-block;
+ flex-shrink: 0;
+ overflow: visible; // IE11
+ vertical-align: middle;
+ padding: @plyr-control-padding;
+ border: 0;
+ background: transparent;
+ border-radius: 3px;
+ cursor: pointer;
+ transition: background 0.3s ease, color 0.3s ease, opacity 0.3s ease;
+ color: inherit;
+
+ svg {
+ width: @plyr-control-icon-size;
+ height: @plyr-control-icon-size;
+ display: block;
+ fill: currentColor;
+ pointer-events: none;
+ }
+
+ // Hide toggle icons by default
+ .icon--exit-fullscreen,
+ .icon--muted,
+ .icon--captions-on {
+ display: none;
+ }
+
+ // Default focus
+ &:focus {
+ outline: 0;
+ }
+}
+
+// Audio styles
+.plyr--audio .plyr__control {
+ &.tab-focus,
+ &:hover,
+ &[aria-expanded='true'] {
+ background: @plyr-audio-control-bg-hover;
+ color: @plyr-audio-control-color-hover;
+ }
+}
+
+// Large play button (video only)
+.plyr__play-large {
+ display: none;
+ position: absolute;
+ z-index: 1;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ padding: ceil(@plyr-control-spacing * 1.25);
+ background: fade(@plyr-video-control-bg-hover, 80%);
+ border: 3px solid currentColor;
+ border-radius: 100%;
+ box-shadow: 0 1px 1px fade(#000, 15%);
+ color: @plyr-video-control-color;
+ transition: all 0.3s ease;
+
+ svg {
+ position: relative;
+ left: 2px;
+ width: 20px;
+ height: 20px;
+ display: block;
+ fill: currentColor;
+ pointer-events: none;
+ }
+
+ &:hover,
+ &:focus {
+ background: @plyr-video-control-bg-hover;
+ }
+
+ &:focus {
+ outline: 1px dotted fade(@plyr-video-control-color, 50%);
+ }
+}
+
+.plyr--full-ui.plyr--video .plyr__play-large {
+ display: inline-block;
+}
+
+.plyr--playing .plyr__play-large {
+ opacity: 0;
+ visibility: hidden;
+}
diff --git a/src/less/components/captions.less b/src/less/components/captions.less
new file mode 100644
index 00000000..d2058a13
--- /dev/null
+++ b/src/less/components/captions.less
@@ -0,0 +1,57 @@
+// --------------------------------------------------------------
+// Captions
+// --------------------------------------------------------------
+
+// Hide default captions
+.plyr--full-ui video::-webkit-media-text-track-container {
+ display: none;
+}
+
+.plyr__captions {
+ display: none;
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ width: 100%;
+ padding: @plyr-control-spacing;
+ transform: translateY(-(@plyr-control-spacing * 4));
+ transition: transform 0.3s ease;
+ color: @plyr-captions-color;
+ font-size: @plyr-font-size-captions-small;
+ text-align: center;
+
+ span {
+ border-radius: 2px;
+ padding: 0.2em 0.5em;
+ background: @plyr-captions-bg;
+ box-decoration-break: clone;
+ line-height: 170%;
+ white-space: pre-wrap;
+
+ // Firefox adds a <div> when using getCueAsHTML()
+ div {
+ display: inline;
+ }
+ }
+
+ span:empty {
+ display: none;
+ }
+
+ @media (min-width: @plyr-bp-screen-sm) {
+ padding: (@plyr-control-spacing * 2);
+ font-size: @plyr-font-size-captions-base;
+ }
+
+ @media (min-width: @plyr-bp-screen-md) {
+ font-size: @plyr-font-size-captions-medium;
+ }
+}
+
+.plyr--captions-active .plyr__captions {
+ display: block;
+}
+
+.plyr--hide-controls .plyr__captions {
+ transform: translateY(-(@plyr-control-spacing * 1.5));
+}
diff --git a/src/less/components/controls.less b/src/less/components/controls.less
new file mode 100644
index 00000000..2750de32
--- /dev/null
+++ b/src/less/components/controls.less
@@ -0,0 +1,127 @@
+// --------------------------------------------------------------
+// Controls
+// --------------------------------------------------------------
+
+// Hide native controls
+.plyr ::-webkit-media-controls {
+ display: none;
+}
+
+// Playback controls
+.plyr__controls {
+ display: flex;
+ align-items: center;
+ text-align: center;
+
+ // Spacing
+ > .plyr__control,
+ .plyr__progress,
+ .plyr__time,
+ .plyr__menu {
+ margin-left: (@plyr-control-spacing / 2);
+
+ &:first-child,
+ &:first-child + [data-plyr='pause'] {
+ margin-left: 0;
+ }
+ }
+
+ .plyr__volume {
+ margin-left: (@plyr-control-spacing / 2);
+ }
+
+ @media (min-width: @plyr-bp-screen-sm) {
+ > .plyr__control,
+ .plyr__progress,
+ .plyr__time,
+ .plyr__menu {
+ margin-left: @plyr-control-spacing;
+ }
+
+ > .plyr__control + .plyr__control,
+ .plyr__menu + .plyr__control,
+ > .plyr__control + .plyr__menu {
+ margin-left: (@plyr-control-spacing / 2);
+ }
+ }
+}
+
+// Video controls
+.plyr--video .plyr__controls {
+ position: absolute;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ z-index: 2;
+ padding: (@plyr-control-spacing * 3.5) (@plyr-control-spacing + 2) @plyr-control-spacing;
+ background: linear-gradient(fade(@plyr-video-controls-bg, 0%), fade(@plyr-video-controls-bg, 70%));
+ border-bottom-left-radius: inherit;
+ border-bottom-right-radius: inherit;
+ color: @plyr-video-control-color;
+ transition: all 0.4s ease-in-out;
+
+ .plyr__control {
+ svg {
+ filter: drop-shadow(0 1px 1px fade(#000, 15%));
+ }
+
+ // Hover and tab focus
+ &.tab-focus,
+ &:hover,
+ &[aria-expanded='true'] {
+ background: @plyr-video-control-bg-hover;
+ color: @plyr-video-control-color-hover;
+ }
+ }
+}
+
+// Hide controls
+.plyr--video.plyr--hide-controls .plyr__controls {
+ opacity: 0;
+ transform: translateY(100%);
+ pointer-events: none;
+}
+
+// Audio controls
+.plyr--audio .plyr__controls {
+ padding: @plyr-control-spacing;
+ border-radius: inherit;
+ background: @plyr-audio-controls-bg;
+ border: @plyr-audio-controls-border;
+ color: @plyr-audio-control-color;
+}
+
+// States
+.plyr__controls [data-plyr='pause'] {
+ display: none;
+}
+.plyr--playing .plyr__controls [data-plyr='play'] {
+ display: none;
+}
+.plyr--playing .plyr__controls [data-plyr='pause'] {
+ display: inline-block;
+}
+
+// Change icons on state change
+.plyr--muted .plyr__control .icon--muted,
+.plyr--captions-active .plyr__control .icon--captions-on {
+ display: block;
+
+ & + svg {
+ display: none;
+ }
+}
+
+// Some options are hidden by default
+.plyr [data-plyr='captions'],
+ .plyr [data-plyr='pip'],
+ .plyr [data-plyr='airplay'],
+ .plyr [data-plyr='fullscreen'] {
+ display: none;
+}
+.plyr--captions-enabled [data-plyr='captions'],
+ .plyr--pip-supported [data-plyr='pip'],
+ .plyr--airplay-supported [data-plyr='airplay'],
+ .plyr--fullscreen-enabled [data-plyr='fullscreen'] {
+ display: inline-block;
+}
diff --git a/src/less/components/embed.less b/src/less/components/embed.less
new file mode 100644
index 00000000..02b33425
--- /dev/null
+++ b/src/less/components/embed.less
@@ -0,0 +1,23 @@
+// --------------------------------------------------------------
+// Embedded players
+// YouTube, Vimeo, etc
+// --------------------------------------------------------------
+
+.plyr__video-embed {
+ padding-bottom: 56.25%; /* 16:9 */
+ height: 0;
+
+ iframe {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ border: 0;
+ user-select: none;
+ }
+}
+// To allow mouse events to be captured if full support
+.plyr--full-ui .plyr__video-embed iframe {
+ pointer-events: none;
+}
diff --git a/src/less/components/menus.less b/src/less/components/menus.less
new file mode 100644
index 00000000..52b735de
--- /dev/null
+++ b/src/less/components/menus.less
@@ -0,0 +1,155 @@
+// --------------------------------------------------------------
+// Menus
+// --------------------------------------------------------------
+
+.plyr__menu {
+ position: relative;
+
+ // Animate the icon
+ .plyr__control svg {
+ transition: transform 0.3s ease;
+ }
+ .plyr__control[aria-expanded='true'] {
+ svg {
+ transform: rotate(45deg);
+ }
+
+ // Hide tooltip
+ .plyr__tooltip {
+ display: none;
+ }
+ }
+
+ // The actual menu container
+ &__container {
+ position: absolute;
+ z-index: 1;
+ bottom: 100%;
+ right: -3px;
+ margin-bottom: 10px;
+ animation: plyr-popup 0.2s ease;
+ background: @plyr-menu-bg;
+ border-radius: 4px;
+ box-shadow: 0 1px 2px fade(#000, 20%);
+ white-space: nowrap;
+ text-align: left;
+ color: @plyr-menu-color;
+ font-size: @plyr-font-size-small;
+
+ > div {
+ overflow: hidden;
+ transition: height 0.35s cubic-bezier(0.4, 0, 0.2, 1), width 0.35s cubic-bezier(0.4, 0, 0.2, 1);
+ }
+
+ // Arrow
+ &::after {
+ content: '';
+ position: absolute;
+ top: 100%;
+ right: 15px;
+ height: 0;
+ width: 0;
+ border: 4px solid transparent;
+ border-top-color: @plyr-menu-bg;
+ }
+
+ ul {
+ margin: 0;
+ padding: @plyr-control-padding;
+ list-style: none;
+ overflow: hidden;
+ }
+
+ // Options
+ .plyr__control {
+ display: flex;
+ align-items: center;
+ width: 100%;
+ padding: ceil(@plyr-control-padding / 2) (@plyr-control-padding * 2);
+ color: @plyr-menu-color;
+ font-weight: @plyr-font-weight-bold;
+ user-select: none;
+
+ &::after {
+ content: '';
+ position: absolute;
+ top: 50%;
+ transform: translateY(-50%);
+ border: 4px solid transparent;
+ transition: border-color 0.2s ease;
+ }
+
+ &--forward {
+ padding-right: ceil(@plyr-control-padding * 4);
+
+ &::after {
+ right: 5px;
+ border-left-color: fade(@plyr-menu-color, 80%);
+ }
+
+ &.tab-focus::after,
+ &:hover::after {
+ border-left-color: currentColor;
+ }
+ }
+
+ &--back {
+ position: relative;
+ @horizontal-padding: (@plyr-control-padding * 2);
+
+ width: ~'calc(100% - @{horizontal-padding})';
+ margin: @plyr-control-padding;
+ margin-bottom: floor(@plyr-control-padding / 2);
+ padding-left: ceil(@plyr-control-padding * 4);
+ font-weight: @plyr-font-weight-normal;
+
+ &::after {
+ left: @plyr-control-padding;
+ border-right-color: fade(@plyr-menu-color, 80%);
+ }
+
+ &::before {
+ content: '';
+ position: absolute;
+ top: 100%;
+ left: 0;
+ right: 0;
+ height: 1px;
+ overflow: hidden;
+ margin-top: ceil(@plyr-control-padding / 2);
+ background: fade(#000, 15%);
+ box-shadow: 0 1px 0 fade(#fff, 10%);
+ }
+
+ &.tab-focus::after,
+ &:hover::after {
+ border-right-color: currentColor;
+ }
+ }
+ }
+
+ label.plyr__control {
+ padding-left: ceil(@plyr-control-padding * 2.5);
+
+ input[type='radio'] {
+ position: relative;
+ left: -@plyr-control-padding;
+ }
+ }
+
+ // Option value
+ .plyr__menu__value {
+ display: flex;
+ align-items: center;
+ margin-left: auto;
+ padding-left: ceil(@plyr-control-padding * 3.5);
+ pointer-events: none;
+ overflow: hidden;
+ font-weight: @plyr-font-weight-normal;
+
+ .plyr__badge {
+ font-weight: @plyr-font-weight-bold;
+ }
+ }
+ }
+}
diff --git a/src/less/components/progress.less b/src/less/components/progress.less
new file mode 100644
index 00000000..0022dfe0
--- /dev/null
+++ b/src/less/components/progress.less
@@ -0,0 +1,110 @@
+// --------------------------------------------------------------
+// Playback progress
+// --------------------------------------------------------------
+
+.plyr__progress {
+ position: relative;
+ display: none;
+ flex: 1;
+
+ input[type='range'] {
+ position: relative;
+ z-index: 2;
+ }
+
+ // Seek tooltip to show time
+ .plyr__tooltip {
+ left: 0;
+ }
+}
+
+.plyr .plyr__progress {
+ display: inline-block;
+}
+
+.plyr__progress--buffer {
+ position: absolute;
+ left: 0;
+ top: 50%;
+ width: 100%;
+ height: @plyr-range-track-height;
+ margin: -(@plyr-range-track-height / 2) 0 0;
+ padding: 0;
+ background: transparent;
+ border: none;
+ border-radius: 100px;
+
+ // WebKit
+ -webkit-appearance: none;
+
+ &::-webkit-progress-bar {
+ background: transparent;
+ }
+
+ &::-webkit-progress-value {
+ background: currentColor;
+ border-radius: 100px;
+ min-width: @plyr-range-track-height;
+ }
+
+ // Mozilla
+ &::-moz-progress-bar {
+ background: currentColor;
+ border-radius: 100px;
+ min-width: @plyr-range-track-height;
+ }
+
+ // Microsoft
+ &::-ms-fill {
+ border-radius: 100px;
+ }
+}
+
+.plyr__progress--buffer {
+ &::-webkit-progress-value {
+ transition: width 0.2s ease;
+ }
+
+ &::-moz-progress-bar {
+ transition: width 0.2s ease;
+ }
+
+ &::-ms-fill {
+ transition: width 0.2s ease;
+ }
+}
+
+.plyr--video .plyr__progress--buffer {
+ box-shadow: 0 1px 1px fade(#000, 15%);
+ color: @plyr-video-progress-buffered-bg;
+}
+
+.plyr--audio .plyr__progress--buffer {
+ color: @plyr-audio-progress-buffered-bg;
+}
+
+// Loading state
+.plyr--loading .plyr__progress--buffer {
+ animation: plyr-progress 1s linear infinite;
+ background-size: @plyr-progress-loading-size @plyr-progress-loading-size;
+ background-repeat: repeat-x;
+ background-image: linear-gradient(
+ -45deg,
+ @plyr-progress-loading-bg 25%,
+ transparent 25%,
+ transparent 50%,
+ @plyr-progress-loading-bg 50%,
+ @plyr-progress-loading-bg 75%,
+ transparent 75%,
+ transparent
+ );
+ color: transparent;
+}
+
+.plyr--video.plyr--loading .plyr__progress--buffer {
+ background-color: @plyr-video-progress-buffered-bg;
+}
+
+.plyr--audio.plyr--loading .plyr__progress--buffer {
+ background-color: @plyr-audio-progress-buffered-bg;
+}
diff --git a/src/less/components/sliders.less b/src/less/components/sliders.less
new file mode 100644
index 00000000..e2a5ffcf
--- /dev/null
+++ b/src/less/components/sliders.less
@@ -0,0 +1,140 @@
+// --------------------------------------------------------------
+// Slider inputs - <input type="range">
+// --------------------------------------------------------------
+
+// Specificity is for bootstrap compatibility
+.plyr--full-ui input[type='range'] {
+ display: block;
+ height: (@plyr-range-thumb-height * @plyr-range-thumb-active-scale);
+ width: 100%;
+ margin: 0;
+ padding: 0;
+ cursor: pointer;
+ border: none;
+ background: transparent;
+
+ // Used in JS to populate lower fill for WebKit
+ color: @plyr-range-selected-bg;
+
+ // WebKit
+ -webkit-appearance: none;
+
+ &::-webkit-slider-runnable-track {
+ .plyr-range-track();
+ }
+
+ &::-webkit-slider-thumb {
+ -webkit-appearance: none;
+ margin-top: -((@plyr-range-thumb-height - @plyr-range-track-height) / 2);
+ .plyr-range-thumb();
+ }
+
+ // Mozilla
+ &::-moz-range-track {
+ .plyr-range-track();
+ }
+
+ &::-moz-range-thumb {
+ .plyr-range-thumb();
+ }
+
+ &::-moz-range-progress {
+ height: @plyr-range-track-height;
+ background: currentColor;
+ border-radius: (@plyr-range-track-height / 2);
+ }
+
+ // Microsoft
+ &::-ms-track {
+ height: @plyr-range-track-height;
+ background: transparent;
+ border: 0;
+ color: transparent;
+ }
+
+ &::-ms-fill-upper {
+ .plyr-range-track();
+ }
+
+ &::-ms-fill-lower {
+ .plyr-range-track();
+
+ background: currentColor;
+ }
+
+ &::-ms-thumb {
+ .plyr-range-thumb();
+ // For some reason, Edge uses the -webkit margin above
+ margin-top: 0;
+ }
+
+ &::-ms-tooltip {
+ display: none;
+ }
+
+ // Focus styles
+ &:focus {
+ outline: 0;
+ }
+
+ &::-moz-focus-outer {
+ border: 0;
+ }
+
+ &.tab-focus {
+ outline-offset: 3px;
+ }
+
+ // Pressed styles
+ &:active {
+ &::-webkit-slider-thumb {
+ .plyr-range-thumb-active();
+ }
+
+ &::-moz-range-thumb {
+ .plyr-range-thumb-active();
+ }
+
+ &::-ms-thumb {
+ .plyr-range-thumb-active();
+ }
+ }
+}
+
+// Video range inputs
+.plyr--full-ui.plyr--video input[type='range'] {
+ &::-webkit-slider-runnable-track {
+ background: @plyr-video-range-track-bg;
+ }
+
+ &::-moz-range-track {
+ background: @plyr-video-range-track-bg;
+ }
+
+ &::-ms-track {
+ background: @plyr-video-range-track-bg;
+ }
+
+ &.tab-focus {
+ outline: 1px dotted fade(@plyr-video-control-color, 50%);
+ }
+}
+
+// Audio range inputs
+.plyr--full-ui.plyr--audio input[type='range'] {
+ &::-webkit-slider-runnable-track {
+ background: @plyr-audio-range-track-bg;
+ }
+
+ &::-moz-range-track {
+ background: @plyr-audio-range-track-bg;
+ }
+
+ &::-ms-track {
+ background: @plyr-audio-range-track-bg;
+ }
+
+ &.tab-focus {
+ outline: 1px dotted fade(@plyr-audio-control-color, 50%);
+ }
+}
diff --git a/src/less/components/times.less b/src/less/components/times.less
new file mode 100644
index 00000000..ea4466d1
--- /dev/null
+++ b/src/less/components/times.less
@@ -0,0 +1,28 @@
+// --------------------------------------------------------------
+// Time
+// --------------------------------------------------------------
+
+.plyr__time {
+ display: inline-block;
+ vertical-align: middle;
+ font-size: @plyr-font-size-small;
+}
+
+// Media duration hidden on small screens
+.plyr__time + .plyr__time {
+ display: none;
+
+ @media (min-width: @plyr-bp-screen-md) {
+ display: inline-block;
+ }
+
+ // Add a slash in before
+ &::before {
+ content: '\2044';
+ margin-right: @plyr-control-spacing;
+ }
+}
+
+.plyr--video .plyr__time {
+ text-shadow: 0 1px 1px fade(#000, 15%);
+}
diff --git a/src/less/components/tooltips.less b/src/less/components/tooltips.less
new file mode 100644
index 00000000..0f7c0071
--- /dev/null
+++ b/src/less/components/tooltips.less
@@ -0,0 +1,87 @@
+// --------------------------------------------------------------
+// Tooltips
+// --------------------------------------------------------------
+
+.plyr__tooltip {
+ position: absolute;
+ z-index: 2;
+ bottom: 100%;
+ margin-bottom: (@plyr-tooltip-padding * 2);
+ padding: @plyr-tooltip-padding (@plyr-tooltip-padding * 1.5);
+ pointer-events: none;
+ opacity: 0;
+ background: @plyr-tooltip-bg;
+ border-radius: @plyr-tooltip-radius;
+ box-shadow: 0 1px 2px fade(#000, 10%);
+ color: @plyr-tooltip-color;
+ font-size: @plyr-font-size-small;
+ font-weight: @plyr-font-weight-normal;
+ line-height: 1.3;
+ transform: translate(-50%, 10px) scale(0.8);
+ transform-origin: 50% 100%;
+ transition: transform 0.2s 0.1s ease, opacity 0.2s 0.1s ease;
+
+ &::before {
+ // Arrows
+ content: '';
+ position: absolute;
+ width: 0;
+ height: 0;
+ left: 50%;
+ transform: translateX(-50%);
+
+ // The background triangle
+ bottom: -@plyr-tooltip-arrow-size;
+ border-right: @plyr-tooltip-arrow-size solid transparent;
+ border-top: @plyr-tooltip-arrow-size solid @plyr-tooltip-bg;
+ border-left: @plyr-tooltip-arrow-size solid transparent;
+ z-index: 2;
+ }
+}
+
+// Displaying
+.plyr .plyr__control:hover .plyr__tooltip,
+.plyr .plyr__control.tab-focus .plyr__tooltip,
+.plyr__tooltip--visible {
+ opacity: 1;
+ transform: translate(-50%, 0) scale(1);
+}
+
+.plyr .plyr__control:hover .plyr__tooltip {
+ z-index: 3;
+}
+
+// First tooltip
+.plyr__controls > .plyr__control:first-child .plyr__tooltip,
+.plyr__controls > .plyr__control:first-child + .plyr__control .plyr__tooltip {
+ left: 0;
+ transform: translate(0, 10px) scale(0.8);
+ transform-origin: 0 100%;
+
+ &::before {
+ left: (@plyr-control-icon-size / 2) + @plyr-control-padding;
+ }
+}
+
+// Last tooltip
+.plyr__controls > .plyr__control:last-child .plyr__tooltip {
+ right: 0;
+ transform: translate(0, 10px) scale(0.8);
+ transform-origin: 100% 100%;
+
+ &::before {
+ left: auto;
+ right: (@plyr-control-icon-size / 2) + @plyr-control-padding;
+ transform: translateX(50%);
+ }
+}
+
+.plyr__controls > .plyr__control:first-child,
+.plyr__controls > .plyr__control:first-child + .plyr__control,
+.plyr__controls > .plyr__control:last-child {
+ &:hover .plyr__tooltip,
+ &.tab-focus .plyr__tooltip,
+ .plyr__tooltip--visible {
+ transform: translate(0, 0) scale(1);
+ }
+}
diff --git a/src/less/components/video.less b/src/less/components/video.less
new file mode 100644
index 00000000..b68bac96
--- /dev/null
+++ b/src/less/components/video.less
@@ -0,0 +1,12 @@
+// --------------------------------------------------------------
+// Video styles
+// --------------------------------------------------------------
+
+.plyr__video-wrapper {
+ position: relative;
+ background: #000;
+ border-radius: inherit;
+ // Require z-index to force border-radius
+ z-index: 0;
+ overflow: hidden;
+}
diff --git a/src/less/components/volume.less b/src/less/components/volume.less
new file mode 100644
index 00000000..f62a572f
--- /dev/null
+++ b/src/less/components/volume.less
@@ -0,0 +1,30 @@
+// --------------------------------------------------------------
+// Volume
+// --------------------------------------------------------------
+
+.plyr__volume {
+ flex: 1;
+ position: relative;
+
+ input[type='range'] {
+ position: relative;
+ z-index: 2;
+ }
+
+ @media (min-width: @plyr-bp-screen-sm) {
+ display: block;
+ max-width: 60px;
+ }
+
+ @media (min-width: @plyr-bp-screen-md) {
+ max-width: 100px;
+ }
+}
+
+// Hide sound controls on iOS
+// It's not supported to change volume using JavaScript:
+// https://developer.apple.com/library/safari/documentation/AudioVideo/Conceptual/Using_HTML5_Audio_Video/Device-SpecificConsiderations/Device-SpecificConsiderations.html
+.plyr--is-ios .plyr__volume,
+ .plyr--is-ios [data-plyr='mute'] {
+ display: none !important;
+}
diff --git a/src/less/lib/animation.less b/src/less/lib/animation.less
new file mode 100644
index 00000000..4165a7f7
--- /dev/null
+++ b/src/less/lib/animation.less
@@ -0,0 +1,21 @@
+// --------------------------------------------------------------
+// Animations
+// --------------------------------------------------------------
+
+@keyframes plyr-progress {
+ to {
+ background-position: @plyr-progress-loading-size 0;
+ }
+}
+
+@keyframes plyr-popup {
+ from {
+ transform: translateY(10px);
+ opacity: 0.5;
+ }
+
+ to {
+ transform: translateY(0);
+ opacity: 1;
+ }
+}
diff --git a/src/less/mixins.less b/src/less/lib/mixins.less
index 14e7d742..333f6afe 100644
--- a/src/less/mixins.less
+++ b/src/less/lib/mixins.less
@@ -11,6 +11,7 @@
border-radius: (@plyr-range-track-height / 2);
user-select: none;
}
+
.plyr-range-thumb() {
position: relative;
height: @plyr-range-thumb-height;
@@ -22,6 +23,7 @@
box-shadow: @plyr-range-thumb-shadow;
box-sizing: border-box;
}
+
.plyr-range-thumb-active() {
background: @plyr-range-thumb-active-bg;
border-color: @plyr-range-thumb-active-border-color;
@@ -38,10 +40,12 @@
video {
height: 100%;
}
+
.plyr__video-wrapper {
height: 100%;
width: 100%;
}
+
.plyr__video-embed {
// Revert overflow change
overflow: visible;
diff --git a/src/less/plyr.less b/src/less/plyr.less
deleted file mode 100644
index a31e7280..00000000
--- a/src/less/plyr.less
+++ /dev/null
@@ -1,957 +0,0 @@
-// ==========================================================================
-// Plyr styles
-// https://github.com/sampotts/plyr
-// TODO: break into smaller files and look at use of BEM classnames
-// ==========================================================================
-
-@import 'variables';
-@import 'mixins';
-
-// Animation
-// ---------------------------------------
-@keyframes plyr-progress {
- to {
- background-position: @plyr-progress-loading-size 0;
- }
-}
-@keyframes plyr-popup {
- from {
- transform: translateY(10px);
- opacity: 0.5;
- }
- to {
- transform: translateY(0);
- opacity: 1;
- }
-}
-
-// Styles
-// -------------------------------
-// Base
-.plyr {
- position: relative;
- max-width: 100%;
- min-width: 200px;
- overflow: hidden;
- font-family: @plyr-font-family;
- font-weight: @plyr-font-weight-normal;
- direction: ltr;
- text-shadow: none;
-
- & when(@plyr-border-box = true) {
- // border-box everything
- // http://paulirish.com/2012/box-sizing-border-box-ftw/
- &,
- *,
- *::after,
- *::before {
- box-sizing: border-box;
- }
- }
-
- & when(@plyr-touch-action = true) {
- // Fix 300ms delay
- a,
- button,
- input,
- label {
- touch-action: manipulation;
- }
- }
-
- // ARIA
- [aria-hidden='true'] {
- display: none;
- }
-
- // Focus
- &:focus {
- outline: 0;
- }
-
- // Media elements
- video,
- audio {
- width: 100%;
- height: auto;
- vertical-align: middle;
- border-radius: inherit;
- }
-
- // Range inputs
- // Specificity is for bootstrap compatibility
- input[type='range'] {
- display: block;
- height: (@plyr-range-thumb-height * @plyr-range-thumb-active-scale);
- width: 100%;
- margin: 0;
- padding: 0;
- cursor: pointer;
- border: none;
- background: transparent;
-
- // Used in JS to populate lower fill for WebKit
- color: @plyr-range-selected-bg;
-
- // WebKit
- -webkit-appearance: none;
-
- &::-webkit-slider-runnable-track {
- .plyr-range-track();
- }
- &::-webkit-slider-thumb {
- -webkit-appearance: none;
- margin-top: -((@plyr-range-thumb-height - @plyr-range-track-height) / 2);
- .plyr-range-thumb();
- }
-
- // Mozilla
- &::-moz-range-track {
- .plyr-range-track();
- }
- &::-moz-range-thumb {
- .plyr-range-thumb();
- }
- &::-moz-range-progress {
- height: @plyr-range-track-height;
- background: currentColor;
- border-radius: (@plyr-range-track-height / 2);
- }
-
- // Microsoft
- &::-ms-track {
- height: @plyr-range-track-height;
- background: transparent;
- border: 0;
- color: transparent;
- }
- &::-ms-fill-upper {
- .plyr-range-track();
- }
- &::-ms-fill-lower {
- .plyr-range-track();
- background: currentColor;
- }
- &::-ms-thumb {
- .plyr-range-thumb();
- // For some reason, Edge uses the -webkit margin above
- margin-top: 0;
- }
- &::-ms-tooltip {
- display: none;
- }
-
- // Focus styles
- &:focus {
- outline: 0;
- }
- &::-moz-focus-outer {
- border: 0;
- }
- &.tab-focus {
- outline-offset: 3px;
- }
-
- // Pressed styles
- &:active {
- &::-webkit-slider-thumb {
- .plyr-range-thumb-active();
- }
- &::-moz-range-thumb {
- .plyr-range-thumb-active();
- }
- &::-ms-thumb {
- .plyr-range-thumb-active();
- }
- }
- }
-}
-
-// Video range inputs
-.plyr--video input[type='range'] {
- &::-webkit-slider-runnable-track {
- background: @plyr-video-range-track-bg;
- }
- &::-moz-range-track {
- background: @plyr-video-range-track-bg;
- }
- &::-ms-track {
- background: @plyr-video-range-track-bg;
- }
-
- &.tab-focus {
- outline: 1px dotted fade(@plyr-video-control-color, 50%);
- }
-}
-
-// Audio range inputs
-.plyr--audio input[type='range'] {
- &::-webkit-slider-runnable-track {
- background: @plyr-audio-range-track-bg;
- }
- &::-moz-range-track {
- background: @plyr-audio-range-track-bg;
- }
- &::-ms-track {
- background: @plyr-audio-range-track-bg;
- }
-
- &.tab-focus {
- outline: 1px dotted fade(@plyr-audio-control-color, 50%);
- }
-}
-
-// Screen reader only elements
-.plyr__sr-only {
- clip: rect(1px, 1px, 1px, 1px);
- overflow: hidden;
-
- // !important is not always needed
- & when(@plyr-sr-only-important = true) {
- position: absolute !important;
- padding: 0 !important;
- border: 0 !important;
- height: 1px !important;
- width: 1px !important;
- }
- & when(@plyr-sr-only-important = false) {
- position: absolute;
- padding: 0;
- border: 0;
- height: 1px;
- width: 1px;
- }
-}
-
-// Video
-.plyr__video-wrapper {
- position: relative;
- background: #000;
- border-radius: inherit;
- // Require z-index to force border-radius
- z-index: 0;
- overflow: hidden;
-}
-
-// Container for embeds
-.plyr__video-embed {
- padding-bottom: 56.25%; /* 16:9 */
- height: 0;
-
- iframe {
- position: absolute;
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
- border: 0;
- user-select: none;
- }
-
- // Vimeo hack
- > div {
- position: relative;
- padding-bottom: 200%;
- transform: translateY(-35.95%);
- }
-}
-// To allow mouse events to be captured if full support
-.plyr .plyr__video-embed iframe {
- pointer-events: none;
-}
-
-// Captions
-// --------------------------------------------------------------
-// Hide default captions
-.plyr video::-webkit-media-text-track-container {
- display: none;
-}
-.plyr__captions {
- display: none;
- position: absolute;
- bottom: 0;
- left: 0;
- width: 100%;
- padding: @plyr-control-spacing;
- transform: translateY(-(@plyr-control-spacing * 4));
- transition: transform 0.3s ease;
- color: @plyr-captions-color;
- font-size: @plyr-font-size-captions-small;
- text-align: center;
-
- span {
- border-radius: 2px;
- padding: 0.2em 0.5em;
- background: @plyr-captions-bg;
- box-decoration-break: clone;
- line-height: 170%;
- white-space: pre-wrap;
-
- // Firefox adds a <div> when using getCueAsHTML()
- div {
- display: inline;
- }
- }
- span:empty {
- display: none;
- }
-
- @media (min-width: @plyr-bp-screen-sm) {
- padding: (@plyr-control-spacing * 2);
- font-size: @plyr-font-size-captions-base;
- }
- @media (min-width: @plyr-bp-screen-md) {
- font-size: @plyr-font-size-captions-medium;
- }
-}
-.plyr--captions-active .plyr__captions {
- display: block;
-}
-.plyr--hide-controls .plyr__captions {
- transform: translateY(-(@plyr-control-spacing * 1.5));
-}
-
-// Controls
-// --------------------------------------------------------------
-// Hide native controls
-.plyr ::-webkit-media-controls {
- display: none;
-}
-
-// Playback controls
-.plyr__controls {
- display: flex;
- align-items: center;
- text-align: center;
-
- // Spacing
- > .plyr__control,
- .plyr__progress,
- .plyr__time,
- .plyr__menu {
- margin-left: (@plyr-control-spacing / 2);
-
- &:first-child,
- &:first-child + [data-plyr='pause'] {
- margin-left: 0;
- }
- }
- .plyr__volume {
- margin-left: (@plyr-control-spacing / 2);
- }
-
- @media (min-width: @plyr-bp-screen-sm) {
- > .plyr__control,
- .plyr__progress,
- .plyr__time,
- .plyr__menu {
- margin-left: @plyr-control-spacing;
- }
-
- > .plyr__control + .plyr__control,
- .plyr__menu + .plyr__control,
- > .plyr__control + .plyr__menu {
- margin-left: (@plyr-control-spacing / 2);
- }
- }
-}
-
-// Buttons
-.plyr__control {
- position: relative;
- display: inline-block;
- flex-shrink: 0;
- overflow: visible; // IE11
- vertical-align: middle;
- padding: @plyr-control-padding;
- border: 0;
- background: transparent;
- border-radius: 3px;
- cursor: pointer;
- transition: background 0.3s ease, color 0.3s ease, opacity 0.3s ease;
- color: inherit;
-
- svg {
- width: @plyr-control-icon-size;
- height: @plyr-control-icon-size;
- display: block;
- fill: currentColor;
- pointer-events: none;
- }
-
- // Hide toggle icons by default
- .icon--exit-fullscreen,
- .icon--muted,
- .icon--captions-on {
- display: none;
- }
-
- // Default focus
- &:focus {
- outline: 0;
- }
-}
-
-// Video controls
-.plyr--video .plyr__controls {
- position: absolute;
- left: 0;
- right: 0;
- bottom: 0;
- z-index: 2;
- padding: (@plyr-control-spacing * 3.5) (@plyr-control-spacing + 2) @plyr-control-spacing;
- background: linear-gradient(fade(@plyr-video-controls-bg, 0%), fade(@plyr-video-controls-bg, 70%));
- border-bottom-left-radius: inherit;
- border-bottom-right-radius: inherit;
- color: @plyr-video-control-color;
- transition: all 0.4s ease-in-out;
-
- .plyr__control {
- svg {
- filter: drop-shadow(0 1px 1px fade(#000, 15%));
- }
-
- // Hover and tab focus
- &.tab-focus,
- &:hover,
- &[aria-expanded='true'] {
- background: @plyr-video-control-bg-hover;
- color: @plyr-video-control-color-hover;
- }
- }
-}
-// Hide controls
-.plyr--video.plyr--hide-controls .plyr__controls {
- opacity: 0;
- transform: translateY(100%);
- pointer-events: none;
-}
-
-// Audio controls
-.plyr--audio .plyr__controls {
- padding: @plyr-control-spacing;
- border-radius: inherit;
- background: @plyr-audio-controls-bg;
- border: @plyr-audio-controls-border;
- color: @plyr-audio-control-color;
-
- .plyr__control {
- // Hover and tab focus
- &.tab-focus,
- &:hover,
- &[aria-expanded='true'] {
- background: @plyr-audio-control-bg-hover;
- color: @plyr-audio-control-color-hover;
- }
- }
-}
-
-// Large play button (video only)
-.plyr__play-large {
- display: none;
- position: absolute;
- z-index: 1;
- top: 50%;
- left: 50%;
- transform: translate(-50%, -50%);
- padding: ceil(@plyr-control-spacing * 1.25);
- background: fade(@plyr-video-control-bg-hover, 80%);
- border: 3px solid currentColor;
- border-radius: 100%;
- box-shadow: 0 1px 1px fade(#000, 15%);
- color: @plyr-video-control-color;
- transition: all 0.3s ease;
-
- svg {
- position: relative;
- left: 2px;
- width: 20px;
- height: 20px;
- display: block;
- fill: currentColor;
- pointer-events: none;
- }
-
- &:hover,
- &:focus {
- background: @plyr-video-control-bg-hover;
- }
-
- &:focus {
- outline: 1px dotted fade(@plyr-video-control-color, 50%);
- }
-}
-.plyr .plyr__play-large {
- display: inline-block;
-}
-.plyr--audio .plyr__play-large {
- display: none;
-}
-.plyr--playing .plyr__play-large {
- opacity: 0;
- visibility: hidden;
-}
-
-// States
-.plyr__controls [data-plyr='pause'],
-.plyr--playing .plyr__controls [data-plyr='play'] {
- display: none;
-}
-.plyr--playing .plyr__controls [data-plyr='pause'] {
- display: inline-block;
-}
-
-// Change icons on state change
-.plyr--muted .plyr__control .icon--muted,
-.plyr--captions-active .plyr__control .icon--captions-on {
- display: block;
-
- & + svg {
- display: none;
- }
-}
-
-// Some options are hidden by default
-.plyr [data-plyr='captions'],
-.plyr [data-plyr='pip'],
-.plyr [data-plyr='airplay'],
-.plyr [data-plyr='fullscreen'] {
- display: none;
-}
-.plyr--captions-enabled [data-plyr='captions'],
-.plyr--pip-supported [data-plyr='pip'],
-.plyr--airplay-supported [data-plyr='airplay'],
-.plyr--fullscreen-enabled [data-plyr='fullscreen'] {
- display: inline-block;
-}
-
-// Menus
-// --------------------------------------------------------------
-.plyr__menu {
- position: relative;
-
- // Hide tooltip
- .plyr__control svg {
- transition: transform 0.3s ease;
- }
- .plyr__control[aria-expanded='true'] {
- svg {
- transform: rotate(45deg);
- }
- .plyr__tooltip {
- display: none;
- }
- }
-
- // The actual menu container
- &__container {
- position: absolute;
- z-index: 1;
- bottom: 100%;
- right: -3px;
- margin-bottom: 10px;
- animation: plyr-popup 0.2s ease;
-
- background: @plyr-menu-bg;
- border-radius: 4px;
- box-shadow: 0 1px 2px fade(#000, 20%);
-
- white-space: nowrap;
- text-align: left;
- color: @plyr-menu-color;
- font-size: @plyr-font-size-small;
-
- > div {
- overflow: hidden;
- transition: height 0.35s cubic-bezier(0.4, 0, 0.2, 1), width 0.35s cubic-bezier(0.4, 0, 0.2, 1);
- }
-
- // Arrow
- &::after {
- content: '';
- position: absolute;
- top: 100%;
- right: 15px;
- height: 0;
- width: 0;
- border: 4px solid transparent;
- border-top-color: @plyr-menu-bg;
- }
-
- ul {
- margin: 0;
- padding: @plyr-control-padding;
- list-style: none;
- overflow: hidden;
- }
-
- // Options
- .plyr__control {
- display: flex;
- align-items: center;
- width: 100%;
- padding: ceil(@plyr-control-padding / 2) (@plyr-control-padding * 2);
- color: @plyr-menu-color;
- font-weight: @plyr-font-weight-bold;
- user-select: none;
-
- &::after {
- content: '';
- position: absolute;
- top: 50%;
- transform: translateY(-50%);
- border: 4px solid transparent;
- transition: border-color 0.2s ease;
- }
-
- &--forward {
- padding-right: ceil(@plyr-control-padding * 4);
-
- &::after {
- right: 5px;
- border-left-color: fade(@plyr-menu-color, 80%);
- }
-
- &.tab-focus::after,
- &:hover::after {
- border-left-color: currentColor;
- }
- }
-
- &--back {
- position: relative;
- @horizontal-padding: (@plyr-control-padding * 2);
- width: ~'calc(100% - @{horizontal-padding})';
- margin: @plyr-control-padding;
- margin-bottom: floor(@plyr-control-padding / 2);
- padding-left: ceil(@plyr-control-padding * 4);
- font-weight: @plyr-font-weight-normal;
-
- &::after {
- left: @plyr-control-padding;
- border-right-color: fade(@plyr-menu-color, 80%);
- }
- &::before {
- content: '';
- position: absolute;
- top: 100%;
- left: 0;
- right: 0;
- height: 1px;
- overflow: hidden;
- margin-top: ceil(@plyr-control-padding / 2);
- background: fade(#000, 15%);
- box-shadow: 0 1px 0 fade(#fff, 10%);
- }
-
- &.tab-focus::after,
- &:hover::after {
- border-right-color: currentColor;
- }
- }
- }
-
- label.plyr__control {
- padding-left: ceil(@plyr-control-padding * 2.5);
-
- input[type='radio'] {
- position: relative;
- left: -@plyr-control-padding;
- }
- }
-
- // Option value
- .plyr__menu__value {
- display: flex;
- align-items: center;
- margin-left: auto;
- padding-left: ceil(@plyr-control-padding * 3.5);
- pointer-events: none;
- overflow: hidden;
- font-weight: @plyr-font-weight-normal;
-
- .plyr__badge {
- font-weight: @plyr-font-weight-bold;
- }
- }
- }
-}
-
-// Badge
-// --------------------------------------------------------------
-.plyr__badge {
- padding: 1px 4px;
- border-radius: 2px;
- background: @plyr-menu-color;
- color: @plyr-menu-bg;
- font-size: 10px;
-}
-
-// Tooltips
-// --------------------------------------------------------------
-.plyr__tooltip {
- position: absolute;
- z-index: 2;
- bottom: 100%;
- margin-bottom: (@plyr-tooltip-padding * 2);
- padding: @plyr-tooltip-padding (@plyr-tooltip-padding * 1.5);
- pointer-events: none;
-
- opacity: 0;
- background: @plyr-tooltip-bg;
- border-radius: @plyr-tooltip-radius;
- box-shadow: 0 1px 2px fade(#000, 10%);
-
- color: @plyr-tooltip-color;
- font-size: @plyr-font-size-small;
- font-weight: @plyr-font-weight-normal;
- line-height: 1.3;
-
- transform: translate(-50%, 10px) scale(0.8);
- transform-origin: 50% 100%;
- transition: transform 0.2s 0.1s ease, opacity 0.2s 0.1s ease;
-
- &::before {
- // Arrows
- content: '';
- position: absolute;
- width: 0;
- height: 0;
- left: 50%;
- transform: translateX(-50%);
-
- // The background triangle
- bottom: -@plyr-tooltip-arrow-size;
- border-right: @plyr-tooltip-arrow-size solid transparent;
- border-top: @plyr-tooltip-arrow-size solid @plyr-tooltip-bg;
- border-left: @plyr-tooltip-arrow-size solid transparent;
- z-index: 2;
- }
-}
-.plyr .plyr__control:hover .plyr__tooltip,
-.plyr .plyr__control.tab-focus .plyr__tooltip,
-.plyr__tooltip--visible {
- opacity: 1;
- transform: translate(-50%, 0) scale(1);
-}
-.plyr .plyr__control:hover .plyr__tooltip {
- z-index: 3;
-}
-
-// First tooltip
-.plyr__controls > .plyr__control:first-child .plyr__tooltip,
-.plyr__controls > .plyr__control:first-child + .plyr__control .plyr__tooltip {
- left: 0;
- transform: translate(0, 10px) scale(0.8);
- transform-origin: 0 100%;
-
- &::before {
- left: (@plyr-control-icon-size / 2) + @plyr-control-padding;
- }
-}
-
-// Last tooltip
-.plyr__controls > .plyr__control:last-child .plyr__tooltip {
- right: 0;
- transform: translate(0, 10px) scale(0.8);
- transform-origin: 100% 100%;
-
- &::before {
- left: auto;
- right: (@plyr-control-icon-size / 2) + @plyr-control-padding;
- transform: translateX(50%);
- }
-}
-
-.plyr__controls > .plyr__control:first-child,
-.plyr__controls > .plyr__control:first-child + .plyr__control,
-.plyr__controls > .plyr__control:last-child {
- &:hover .plyr__tooltip,
- &.tab-focus .plyr__tooltip,
- .plyr__tooltip--visible {
- transform: translate(0, 0) scale(1);
- }
-}
-
-// Playback progress
-// --------------------------------------------------------------
-// <progress> element
-.plyr__progress {
- position: relative;
- display: none;
- flex: 1;
-
- input[type='range'] {
- position: relative;
- z-index: 2;
- }
-
- // Seek tooltip to show time
- .plyr__tooltip {
- left: 0;
- }
-}
-.plyr .plyr__progress {
- display: inline-block;
-}
-
-.plyr__progress--buffer {
- position: absolute;
- left: 0;
- top: 50%;
- width: 100%;
- height: @plyr-range-track-height;
- margin: -(@plyr-range-track-height / 2) 0 0;
- padding: 0;
- background: transparent;
- border: none;
- border-radius: 100px;
-
- // WebKit
- -webkit-appearance: none;
-
- &::-webkit-progress-bar {
- background: transparent;
- }
- &::-webkit-progress-value {
- background: currentColor;
- border-radius: 100px;
- min-width: @plyr-range-track-height;
- }
-
- // Mozilla
- &::-moz-progress-bar {
- background: currentColor;
- border-radius: 100px;
- min-width: @plyr-range-track-height;
- }
-
- // Microsoft
- &::-ms-fill {
- border-radius: 100px;
- }
-}
-.plyr__progress--buffer {
- &::-webkit-progress-value {
- transition: width 0.2s ease;
- }
- &::-moz-progress-bar {
- transition: width 0.2s ease;
- }
- &::-ms-fill {
- transition: width 0.2s ease;
- }
-}
-.plyr--video .plyr__progress--buffer {
- box-shadow: 0 1px 1px fade(#000, 15%);
- color: @plyr-video-progress-buffered-bg;
-}
-.plyr--audio .plyr__progress--buffer {
- color: @plyr-audio-progress-buffered-bg;
-}
-
-// Loading state
-.plyr--loading .plyr__progress--buffer {
- animation: plyr-progress 1s linear infinite;
- background-size: @plyr-progress-loading-size @plyr-progress-loading-size;
- background-repeat: repeat-x;
- background-image: linear-gradient(
- -45deg,
- @plyr-progress-loading-bg 25%,
- transparent 25%,
- transparent 50%,
- @plyr-progress-loading-bg 50%,
- @plyr-progress-loading-bg 75%,
- transparent 75%,
- transparent
- );
- color: transparent;
-}
-.plyr--video.plyr--loading .plyr__progress--buffer {
- background-color: @plyr-video-progress-buffered-bg;
-}
-.plyr--audio.plyr--loading .plyr__progress--buffer {
- background-color: @plyr-audio-progress-buffered-bg;
-}
-
-// Time
-// --------------------------------------------------------------
-.plyr__time {
- display: inline-block;
- vertical-align: middle;
- font-size: @plyr-font-size-small;
-}
-// Media duration hidden on small screens
-.plyr__time + .plyr__time {
- display: none;
-
- @media (min-width: @plyr-bp-screen-md) {
- display: inline-block;
- }
-
- // Add a slash in before
- &::before {
- content: '\2044';
- margin-right: @plyr-control-spacing;
- }
-}
-.plyr--video .plyr__time {
- text-shadow: 0 1px 1px fade(#000, 15%);
-}
-
-// Volume
-// --------------------------------------------------------------
-.plyr__volume {
- display: none;
-}
-.plyr .plyr__volume {
- flex: 1;
- position: relative;
-
- input[type='range'] {
- position: relative;
- z-index: 2;
- }
- @media (min-width: @plyr-bp-screen-sm) {
- display: block;
- max-width: 60px;
- }
- @media (min-width: @plyr-bp-screen-md) {
- max-width: 100px;
- }
-}
-
-// Hide sound controls on iOS
-// It's not supported to change volume using JavaScript:
-// https://developer.apple.com/library/safari/documentation/AudioVideo/Conceptual/Using_HTML5_Audio_Video/Device-SpecificConsiderations/Device-SpecificConsiderations.html
-.plyr--is-ios .plyr__volume,
-.plyr--is-ios [data-plyr='mute'] {
- display: none !important;
-}
-
-// Fullscreen
-// --------------------------------------------------------------
-.plyr:fullscreen {
- .plyr-fullscreen-active();
-}
-.plyr:-webkit-full-screen {
- .plyr-fullscreen-active();
-}
-.plyr:-moz-full-screen {
- .plyr-fullscreen-active();
-}
-.plyr:-ms-fullscreen {
- .plyr-fullscreen-active();
-}
-
-// Fallback for unsupported browsers
-.plyr--fullscreen-fallback {
- .plyr-fullscreen-active();
-
- position: fixed;
- top: 0;
- left: 0;
- right: 0;
- bottom: 0;
- z-index: 10000000;
-}
diff --git a/src/less/variables.less b/src/less/settings.less
index e1b3f64b..e1b3f64b 100644
--- a/src/less/variables.less
+++ b/src/less/settings.less
diff --git a/src/less/states/fullscreen.less b/src/less/states/fullscreen.less
new file mode 100644
index 00000000..9f7478d8
--- /dev/null
+++ b/src/less/states/fullscreen.less
@@ -0,0 +1,31 @@
+// --------------------------------------------------------------
+// Fullscreen
+// --------------------------------------------------------------
+
+.plyr:fullscreen {
+ .plyr-fullscreen-active();
+}
+
+.plyr:-webkit-full-screen {
+ .plyr-fullscreen-active();
+}
+
+.plyr:-moz-full-screen {
+ .plyr-fullscreen-active();
+}
+
+.plyr:-ms-fullscreen {
+ .plyr-fullscreen-active();
+}
+
+// Fallback for unsupported browsers
+.plyr--fullscreen-fallback {
+ .plyr-fullscreen-active();
+
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ z-index: 10000000;
+}
diff --git a/src/less/utils/hidden.less b/src/less/utils/hidden.less
new file mode 100644
index 00000000..20947c59
--- /dev/null
+++ b/src/less/utils/hidden.less
@@ -0,0 +1,33 @@
+// --------------------------------------------------------------
+// Hiding content nicely
+// --------------------------------------------------------------
+
+// Attributes
+.plyr--full-ui [hidden] {
+ display: none;
+}
+.plyr--full-ui [aria-hidden='true'] {
+ display: none;
+}
+
+// Screen reader only elements
+.plyr__sr-only {
+ clip: rect(1px, 1px, 1px, 1px);
+ overflow: hidden;
+
+ // !important is not always needed
+ & when(@plyr-sr-only-important = true) {
+ position: absolute !important;
+ padding: 0 !important;
+ border: 0 !important;
+ height: 1px !important;
+ width: 1px !important;
+ }
+ & when(@plyr-sr-only-important = false) {
+ position: absolute;
+ padding: 0;
+ border: 0;
+ height: 1px;
+ width: 1px;
+ }
+}