toolkit/themes/shared/pictureinpicture/player.css

Propagation: 1.47%

Back to Home
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

:root {
  --player-bg-color: #000;
  --player-control-icon-fill: #fff;
  --player-control-item-half-width: clamp(calc(16px / 2), calc(10vmax / 2), calc(32px / 2));
  --player-control-item-height: clamp(16px, 10vmax, 32px);
  --close-btn-fill-color: #000;
  --controls-bottom-distance: 15px;
  --controls-bottom-upper-height: 30px;
  --scrubber-vertical-margin: 7px;
  --resize-margin: 5px;

  background-color: var(--player-bg-color);
  overflow: hidden;
}

body {
  margin: 0;
}

body:fullscreen {
  -moz-window-dragging: no-drag;

  #fullscreen {
    background-image: url("chrome://global/skin/media/picture-in-picture-exit-fullscreen-button.svg");
    background-size: auto;
  }

  #controls {
    &[showing]:hover .control-item:not(:hover) {
      opacity: 0.8;
    }

    /* Hide cursor when we expect controls to be hidden. */
    &:not([showing], [keying], [donthide]) {
      cursor: none;
    }
  }
}

.player-holder {
  display: flex;
  flex-direction: column;
  height: 100vh;
  overflow: hidden;
}

.seethrough-mode {
  background: transparent;

  .player-holder {
    will-change: opacity, filter;
    transition:
      opacity 160ms linear,
      filter 160ms linear;

    body:hover:not(:fullscreen) & {
      opacity: 0.35;
      filter: blur(8px);
    }
  }
}

browser {
  flex: 1;
}

#controls {
  height: calc(100% - 2 * var(--resize-margin));
  left: 0;
  position: absolute;
  top: 0;
  width: calc(100% - 2 * var(--resize-margin));
  margin: var(--resize-margin);
  -moz-window-dragging: drag;
}

#controls button {
  appearance: none;
  border: 0;
  z-index: 1;
}

#controls button:focus-visible,
#controls input:focus-visible,
.switch > input:focus-visible + .slider {
  outline: 3px solid #0060df;
  box-shadow: 1px 2px 5px #000;
}

/* Styling for background gradient.
 * Opacity changes are handled separately under .control-item.
 */
#controls-bottom-gradient {
  background: linear-gradient(0deg, #000000 -13.24%, rgba(0, 0, 0, 0) 90.44%);
  position: absolute;
  height: calc(
    var(--controls-bottom-distance) + 2 * var(--resize-margin) + var(--player-control-item-height) + var(--controls-bottom-upper-height) +
      var(--scrubber-vertical-margin)
  );
  bottom: 0;
  width: 100vw;
  margin: 0 calc(-1 * var(--resize-margin)) calc(-1 * var(--resize-margin)) calc(-1 * var(--resize-margin));
  pointer-events: none;
  -moz-window-dragging: drag;
}

#controls-bottom {
  position: absolute;
  bottom: var(--controls-bottom-distance);
  width: 100%;
}

.controls-bottom-lower {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  margin: 0 24px;
}

.start-controls {
  display: grid;
  justify-self: start;
}

.center-controls {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-areas: "seekbackward playpause seekforward";
  justify-self: center;
  gap: 8px;
}

.end-controls {
  display: grid;
  grid-template-columns: 1fr 2fr 1fr 1fr;
  grid-template-areas: "audio audio-scrubber closedcaption fullscreen";
  justify-self: end;
  gap: 8px;
}

.control-item {
  -moz-window-dragging: no-drag;
  transition:
    opacity 160ms linear,
    fill-opacity 160ms linear;
  opacity: 0;
  cursor: pointer;
}

.control-button {
  background-color: transparent;
  border-radius: 4px;
  /**
   * Make the button dimensions a square proportional to one
   * dimension of the window - in this case, the width dimension,
   * since we suspect most videos are wider than they are tall.
   */
  height: var(--player-control-item-height);
  width: 10vmax;
  max-width: 32px;
  min-width: 16px;
  -moz-context-properties: fill, fill-opacity;
  fill: var(--player-control-icon-fill);
  background-position: center;
  background-size: 60%;
  background-repeat: no-repeat;
}

.control-button:hover:enabled {
  background-color: rgba(255, 255, 255, 0.25);
}

#controls:is([keying], [showing]) .control-button:disabled,
/* Only change opacity on hover events for non-fullscreen mode.
 * Fullscreen mode uses the `showing` attribute instead. */
body:not(:fullscreen) #controls:hover .control-button:disabled {
  /* Set `fill-opacity` to the desired opacity in addition to full `opacity`
   * to allow having the button's tooltip in full opacity even if the button is disabled. */
  fill-opacity: 0.4;
  opacity: 1 !important;
}

.control-item:focus-visible::after,
.control-item:hover::after {
  content: attr(tooltip);
  display: inline-block;
  width: max-content;
  position: relative;
  padding: 0.4em 0.5em;
  background: #000000;
  color: #ffffff;
  border-radius: 4px;
  pointer-events: none;
}

/* Since #controls is set to LTR, button tooltips would normally appear
 * as LTR also for RTL locales. To fix this, set the .control-item's ::after
 * to RTL based on the root directionality.
 * Because of that, don't set logical properties for the next set of rules. */
:root:dir(rtl) .control-item::after {
  direction: rtl;
}

/* Set the tooltip position for different playback controls */

.tooltip-under-controls:focus-visible::after,
.tooltip-under-controls:hover::after {
  bottom: -3em;
}

#close:focus-visible::after,
#close:hover::after,
#unpip[mac="true"]:focus-visible::after,
#unpip[mac="true"]:hover::after {
  float: right;
  transform: translateX(1em);
}

#unpip:focus-visible::after,
#unpip:hover::after,
#close[mac="true"]:focus-visible::after,
#close[mac="true"]:hover::after {
  float: left;
  transform: translateX(-1em);
}

.tooltip-over-controls:focus-visible::after,
.tooltip-over-controls:hover::after {
  bottom: 3em;
}

.inline-end-tooltip:focus-visible::after,
.inline-end-tooltip:hover::after {
  float: right;
  right: -1em;
}

.inline-start-tooltip:focus-visible::after,
.inline-start-tooltip:hover::after {
  float: left;
  left: -1em;
}

.center-tooltip:focus-visible::after,
.center-tooltip:hover::after {
  right: 0.8em;
  translate: calc(-50% + var(--player-control-item-half-width));
}

/* Since the unpip button icon is reversed for RTL locales,
 * re-position the tooltip so that the tooltip remains in the original placement */
:root:dir(rtl) #unpip:focus-visible::after,
:root:dir(rtl) #unpip:hover::after {
  float: right;
}

:root:dir(rtl) #unpip[mac="true"]:focus-visible::after,
:root:dir(rtl) #unpip[mac="true"]:hover::after {
  float: left;
}

/* Since the unpip icon is reversed for RTL locales,
 * flip its tooltip back */
:root:dir(rtl) #unpip:focus-visible::after,
:root:dir(rtl) #unpip:hover::after {
  scale: -1 1;
}

/* Set opacity for buttons and scrubber when controls are visible on the pip
 * window and are not hovered over. */
body:not(:fullscreen) #controls:hover .control-item:not(:hover),
#controls[donthide] .control-item {
  opacity: 0.8;
}

#controls[keying] .control-item,
#controls[showing] .control-item,
.control-item:hover {
  opacity: 1;
}

/* Background gradient is the only control item with a fixed opacity value. */
#controls[keying] #controls-bottom-gradient,
#controls[showing] #controls-bottom-gradient,
#controls-bottom-gradient:hover {
  opacity: 0.8;
}

/* For readability, timestamp should maintain full opacity when visible */
body:not(:fullscreen) #controls:hover #timestamp {
  opacity: 1;
}

#close,
#unpip {
  background-color: rgba(255, 255, 255, 0.8);
  position: absolute;
  fill: var(--close-btn-fill-color);
}

#close:is(:hover, :focus-visible),
#unpip:is(:hover, :focus-visible) {
  background-color: rgba(255, 255, 255, 0.9);
}

#close {
  background-image: url("chrome://global/skin/icons/close.svg");
  right: 10px;
  top: 10px;
}

#close[mac="true"] {
  right: auto;
  left: 10px;
}

#unpip {
  background-image: url("chrome://global/skin/media/picture-in-picture-closed.svg");
  left: 10px;
  top: 10px;
}

#unpip[mac="true"] {
  right: 10px;
  left: auto;
}

#playpause {
  grid-area: playpause;
}

#audio {
  grid-area: audio;
}

#audio-scrubber {
  grid-area: audio-scrubber;
  align-self: center;
  width: 64px;
  background-color: transparent;
  padding: 6px 2px;
  margin: 0;

  &::-moz-range-thumb {
    border-radius: 8px;
    background-color: #ffffff;
    width: 8px;
    height: 8px;
    padding: 0;
  }

  &::-moz-range-track {
    background-color: #969696;
  }

  &::-moz-range-progress {
    background-color: #ffffff;
  }

  &,
  &::-moz-range-track,
  &::-moz-range-progress {
    height: 2px;
    border-radius: 10px;
  }
}

#fullscreen {
  grid-area: fullscreen;
}

#controls.playing #playpause {
  background-image: url("chrome://global/skin/media/pause-fill.svg");
}

#controls:not(.playing) #playpause {
  background-image: url("chrome://global/skin/media/play-fill.svg");
}

#controls.muted #audio {
  background-image: url("chrome://global/skin/media/audio-muted.svg");
}

#controls:not(.muted) #audio {
  background-image: url("chrome://global/skin/media/audio.svg");
}

body:not(:fullscreen) #fullscreen {
  background-image: url("chrome://global/skin/media/picture-in-picture-enter-fullscreen-button.svg");
  background-size: auto;
}

#seekBackward {
  background-image: url("chrome://global/skin/media/picture-in-picture-seekBackward-button.svg");
  background-size: auto;
  grid-area: seekbackward;
}

#seekForward {
  background-image: url("chrome://global/skin/media/picture-in-picture-seekForward-button.svg");
  background-size: auto;
  grid-area: seekforward;
}

:root:dir(rtl) #unpip {
  transform: scaleX(-1);
}

#closed-caption {
  background-image: url("chrome://global/skin/media/closed-caption-settings-button.svg");
  color: white;
  grid-area: closedcaption;
}

.box {
  -moz-window-dragging: no-drag;
  background-color: #2b2a33;
  text-align: start;
  font-size: 1em;
  width: 186px;
  padding: 0 8px;
  margin: 0;
  border-radius: 8px;
}

:root:dir(rtl) .box {
  direction: rtl;
}

.a11y-only {
  visibility: hidden;
  position: absolute;
}

.hide {
  display: none;
}

.bold {
  font-weight: var(--font-weight-bold);
}

.box > input[type="radio"] {
  background-color: red;
  fill: currentColor;
}

.box label:not(.switch) {
  color: white;
  font-family: sans-serif;
}

#subtitles-toggle-label {
  width: fit-content;
  padding: 8px;
}

.panel {
  position: absolute;
  bottom: 40px;
  user-select: none;
  right: 24px;
}

.panel-fieldset {
  border: none;
  margin-top: 8px;
  padding-inline-start: 0;
}

.panel-legend {
  font-family: sans-serif;
  color: white;
  margin-top: 8px;
  padding-inline-start: 0;
}

.arrow {
  border: 10px solid transparent;
  border-top-color: #2b2a33;
  width: 0;
  height: 0;
  inset-inline-start: 136px;
  position: relative;
}

.grey-line {
  width: 100%;
  height: 1px;
  background: #8f8f9d;
}

.font-size-selection {
  margin-inline-start: 8px;
  padding-inline-start: 8px;
}

.font-size-selection-radio {
  display: flex;
  width: fit-content;
  cursor: pointer;
  padding-block: 8px;
}

.font-size-selection-radio label {
  cursor: pointer;
}

.font-size-selection-radio > input[type="radio"] {
  appearance: none;
  width: 16px;
  height: 16px;
  border: 1px solid #8f8f9d;
  border-radius: 50%;
  margin: 0;
  margin-inline-end: 6px;
}

.font-size-selection-radio > input[type="radio"]:checked {
  border: 4px solid #00ddff;
}

.subtitle-grid {
  display: grid;
  grid-template-rows: auto;
  grid-template-columns: auto 46px;
  padding: 8px;
}

.switch {
  position: relative;
  display: inline-block;
  width: 32px;
  height: 16px;
  grid-column: 2;
  margin: 8px;
  cursor: pointer;
}

.switch input {
  opacity: 0;
  width: 0;
  height: 0;
}

.slider {
  position: absolute;
  inset: 0;
  transition: transform 250ms;
  border-radius: 13px;
  background-color: #55545f;
}

.slider::before {
  position: absolute;
  content: "";
  height: 12px;
  width: 12px;
  inset-inline-start: 2px;
  bottom: 2px;
  background-color: #2b2a33;
  transition: transform 250ms;
  border-radius: 50%;
}

input:checked + .slider {
  background-color: #00ddff;
}

input:checked + .slider::before {
  transform: translateX(16px);
}

:root:dir(rtl) input:checked + .slider::before {
  transform: translateX(-16px);
}

.font-size-overlay {
  opacity: 0.4;
  pointer-events: none;
}

.controls-bottom-upper {
  width: calc(100% - 38px);
  height: var(--controls-bottom-upper-height);
  margin: 0 19px;
  display: grid;
}

.scrubber-no-drag {
  -moz-window-dragging: no-drag;
  height: 16px;
  margin: var(--scrubber-vertical-margin) 0;
  display: grid;
  justify-items: center;
  align-items: center;
  width: 100%;
}

#scrubber {
  width: 100%;
  background-color: transparent;
  padding: 6px 2px;

  &::-moz-range-thumb {
    border-radius: 14px;
    background-color: #bfbfc9;
    width: 8px;
    height: 8px;
    border: 3px solid #ffffff;
    padding: 0;
  }

  &::-moz-range-track {
    background-color: #969696;
  }

  &::-moz-range-progress {
    background-color: #ffffff;
  }

  &,
  &::-moz-range-track,
  &::-moz-range-progress {
    height: 4px;
    border-radius: 10px;
  }
}

#timestamp {
  align-self: center;
  color: #ffffff;
  cursor: default;
  font-family: system-ui;
  font-size: 0.9em;
  font-variant-numeric: tabular-nums;
  user-select: none;
  width: 16ch;
  grid-area: timestamp;
}

#timestamp::after {
  background: unset;
  content: unset;
}

@media (width <= 630px) {
  #audio-scrubber {
    display: none;
  }

  .end-controls {
    grid-template-columns: repeat(3, 1fr);
    grid-template-areas: "audio closedcaption fullscreen";
  }
}

@media (width <= 475px) {
  #closed-caption {
    display: none;
  }

  .end-controls {
    grid-template-columns: repeat(2, 1fr);
    grid-template-areas: "audio fullscreen";
  }
}

@media (height <= 325px) and (width > 630px) {
  #closed-caption {
    display: none;
  }

  .end-controls {
    grid-template-columns: 1fr 2fr 1fr;
    grid-template-areas: "audio audio-scrubber fullscreen";
  }
}

@media (height <= 325px) and (width <= 630px) {
  #closed-caption,
  #audio-scrubber {
    display: none;
  }

  .end-controls {
    grid-template-columns: repeat(2, 1fr);
    grid-template-areas: "audio fullscreen";
  }
}

@media (width <= 440px) {
  #timestamp {
    display: none;
  }
}

@media (width <= 350px) {
  #fullscreen {
    display: none;
  }

  .end-controls {
    grid-template-columns: repeat(1, 1fr);
    grid-template-areas: "audio";
  }
}

@media (height <= 200px) {
  .scrubber-no-drag {
    display: none;
  }
}

@media (width <= 300px) {
  .scrubber-no-drag,
  #seekForward,
  #seekBackward,
  .start-controls {
    display: none;
  }

  .controls-bottom-lower {
    grid-template-columns: repeat(2, 1fr);
  }

  .center-controls {
    grid-template-columns: repeat(1, 1fr);
    grid-template-areas: "playpause";
  }

  .end-controls {
    justify-self: center;
  }
}
Back to Home