Der folgende Text ist ein Gastbeitrag von Sara Soueidan. Ich kenne Sara durch ihre ausgezeichnete Arbeit auf CodePen. Sie arbeitete an benutzerdefinierten HTML5-Video-Steuerelementen und stellte fest, dass die Anpassungen verloren gingen, als das Video in den Vollbildmodus wechselte (Beispiel, wie das passiert). Sara taucht in den Shadow DOM ein und findet eine Lösung...
Wenn Sie jemals mit HTML5-Videos gearbeitet haben, haben Sie sich wahrscheinlich gefragt, wie Sie eine Reihe von Steuerelementen, Schiebereglern und Griffen auf Ihrer Seite erhalten, obwohl Sie nur ein einziges <video>-Tag zum DOM hinzugefügt haben.

Browser fügen diese Steuerelemente als „Unterbaum“ des Video-Tags in die Darstellung des Dokuments ein. Diese Elemente (Schaltflächen, Schieberegler usw.) *sind* Teil des DOM, aber Sie können sie im Haupt-DOM-Baum nicht wirklich sehen, Sie sehen sie nur auf der Seite gerendert. Mehr dazu in Kürze.
Das Problem der HTML5-Video-Steuerelemente im Vollbildmodus
Bei der Arbeit an einem benutzerdefinierten HTML5-Video-Framework stieß ich kürzlich auf ein Problem, auf das viele Designer und Entwickler in diesem Bereich stoßen. Anstatt die benutzerdefinierten Steuerelemente anzuzeigen, die ich entwickelt hatte, erschienen beim Wechsel in den Vollbildmodus die nativen Browser-Steuerelemente. Wie so viele andere suchte ich nach Antworten auf dieses Problem, fand aber keine. (Update: Dieser Bug ist im Chrome-Bugtracker eingereicht).
Nach einiger Inspektion in den Entwicklertools stellte ich fest,
- dass die nativen Steuerelemente immer noch da waren. Indem wir das Attribut
controlsdes Video-Elements auffalsesetzen, können wir die Steuerelemente *ausblenden*, aber aus irgendeinem Grund erscheinen sie beim Eintritt in den Vollbildmodus wieder, obwohl sie im normalen Bildschirmmodus ausgeblendet sind. (Warum?) - Die benutzerdefinierten Steuerelemente waren im Vollbildmodus *unter* dem Video verborgen. Die Inspektion der Steuerelemente mit den Entwicklertools zeigte, dass der Grund, warum die Steuerelemente darunter verborgen waren, darin bestand, dass die Stylesheet des User-Agents (in diesem Fall die Stylesheet von Chrome) die auf die Steuerelemente angewendeten Stile überschrieb, mit einem sehr seltsamen
z-index-Wert, muss ich sagen!

Wie machen wir das? Wie verhindern wir, dass die nativen Steuerelemente im Vollbildmodus erscheinen und stattdessen unsere eigenen benutzerdefinierten Steuerelemente anzeigen?
Der zweite Punkt ist einfach: Überschreiben Sie einfach die User-Agent-Stylesheet. Das machen wir ständig in unseren Stylesheets. Dazu kommen wir gleich. Aber was ist mit dem ersten Punkt? Wie können wir Elemente ausblenden, die der Browser hinzufügt, die wir aber nicht im DOM-Baum sehen, mit dem wir arbeiten?
Beachten Sie, dass die in diesem Artikel beschriebene Technik zum Ausblenden der nativen Steuerelemente nur in Browsern funktioniert, die den Shadow DOM unterstützen.
Kurze Einführung in den Shadow DOM
Der vom Browser generierte Unterbaum von DOM-Elementen wird als „Shadow DOM“ bezeichnet. Einfach ausgedrückt handelt es sich um eine Reihe von DOM-Elementen, ähnlich den Ihnen bereits bekannten, wie z. B. <div>s und <span>s, die vom Browser als *Dokumentfragment* hinzugefügt werden und wie der Haupt-DOM-Baum auf der Seite gerendert werden.
James Edwards fasst die Funktion des Shadow DOM perfekt in seinem Artikel für SitePoint zusammen:
Der Shadow DOM kapselt Inhalte, indem er Dokumentfragmente erstellt. Effektiv ist der Inhalt eines Shadow DOM ein *anderes Dokument*, das mit dem Hauptdokument zusammengeführt wird, um die gesamte gerenderte Ausgabe zu erzeugen.
Tatsächlich nutzen einige Browser dies bereits zur Darstellung einiger ihrer nativen Widgets.
Der Grund, warum Browser dies tun, ist, dass Browserentwickler beschlossen haben, einige DOM-Elemente zu kapseln, um sie vor uns Entwicklern zu verbergen, damit wir uns nicht mit den Implementierungsdetails dieser Elemente befassen müssen, um uns die Arbeit zu erleichtern. Wie James Edwards auch in seinem Artikel sagte:
Da er isoliert ist, können Benutzer ihn nicht versehentlich kaputt machen, es gibt keine Möglichkeit für Namenskonflikte mit von Ihnen verwendeten Klassen oder IDs, und das CSS der Hauptseite wirkt sich überhaupt nicht darauf aus.
Wir wissen also jetzt, dass die dem Video-Tag hinzugefügten Steuerelemente nur Teil des vom Browser für dieses Tag generierten Shadow-DOM-Unterbaums sind.
Natives Video-Steuerelemente ausblenden
Wir müssen die Steuerelemente, die Teil des Shadow DOM sind, gestalten können, aber wie machen wir das, wenn die regulären CSS-Selektoren, die wir kennen, nicht auf Shadow DOM-Elemente zugreifen können?
Nachdem ich diesen hervorragenden Einführungsartikel von Dimitri Glazkov gelesen hatte, erfuhr ich, dass es „eine praktische Pseudo-Attribut-Funktionalität gibt, die es Shadow-DOM-Unterbäumen ermöglicht, eine beliebige Pseudo-Element-Kennung mit einem Element im Unterbaum zu verknüpfen.“
Das bedeutet, dass einige Elemente innerhalb des Shadow-DOM-Unterbaums über ihr zugeordnetes Pseudo-Element gestaltet werden können. Das klingt großartig!
Aber wie bestimmen wir, welches Pseudo-Element dem Shadow-DOM-Element zugeordnet ist, das wir gestalten müssen? Einige Elemente sind mehr oder weniger bekannt, wie z. B. das Range-Input-Element, für das in Webkit-Browsern ein Pseudo-Element zur Gestaltung seines Griffs verfügbar ist.
::-webkit-slider-thumb
Firefox bietet ebenfalls zwei Pseudo-Elemente zur Gestaltung von Range-Inputs, seit es diese ab Version 23.0 unterstützt.
::-moz-range-track
und
::-moz-range-thumb
Aber was ist mit anderen weniger bekannten Pseudo-Elementen, die anderen Shadow-DOM-Elementen zugeordnet sind? Welche Pseudo-Elemente sind ihnen zugeordnet? Um das herauszufinden, kommen die Chrome-Entwicklertools zu Hilfe!
Pseudo-Elemente, die Shadow DOM-Elementen zugeordnet sind, ermitteln
Eine der großartigen Funktionen der Chrome-Entwicklertools ist, dass Sie die Shadow-DOM-Unterbäume im Elemente-Panel genauso inspizieren können, wie Sie einen „regulären“ DOM-Baum inspizieren würden. Alles, was Sie tun müssen, ist diese Funktion zu aktivieren:
- Gehen Sie zu den Einstellungen der Entwicklertools (indem Sie auf das kleine Zahnrad-Symbol unten rechts in den Entwicklertools klicken)
- Aktivieren Sie im Reiter „Allgemein“ die Option „Shadow DOM anzeigen“
- Starten Sie die Entwicklertools neu (schließen und wieder öffnen)
Wenn Sie nun das <video>-Element inspizieren, erhalten Sie etwas Ähnliches wie auf dem folgenden Screenshot.

<video>-Element hinzugefügte Shadow-DOM-Unterbaum, inspiziert mit den Chrome-Entwicklertools, zeigt ein neues #document-fragmentDann, genauso wie Sie die Stilregeln für jedes HTML-Element erhalten können, wenn Sie es im Elemente-Panel anklicken, können Sie auch die Pseudo-Elemente sehen, die dem Unterbaum des Shadow DOM zugeordnet sind. Ziemlich raffiniert, oder? :)

<div> innerhalb des Shadow-DOM-Unterbaums zugeordnet ist.Für die Video-Steuerelemente können wir dem Screenshot entnehmen, dass es ein Pseudo-Element namens ::-webkit-media-controls gibt, das, wie der Name schon sagt, Elementen zugeordnet ist, die Medien-Steuerelemente enthalten.
Wenn Sie auf dieses Pseudo-Element display:none !important; setzen, wird das Element im normalen und im Vollbildmodus vollständig ausgeblendet.
::-webkit-media-controls {
display:none !important;
}
Aber bedenken Sie, dass dieses Pseudo-Element dem äußersten <div> im Unterbaum zugeordnet ist, das Medien-Steuerelemente enthalten wird, *allerlei* Medien-Steuerelemente. Das bedeutet, dass Sie auch die Steuerelemente für dieses Medienelement ausblenden, wenn Sie irgendwo auf der Seite ein <audio>-Element haben.
Wenn Sie also nicht *alle* nativen Medien-Steuerelemente des Browsers ausblenden möchten, müssen Sie angeben, welche Art von Medien-Steuerelementen ausgeblendet werden sollen, nämlich diejenigen, die dem Video-Element zugeordnet sind, und Sie würden sie durch Angabe des „Geltungsbereichs“ für dieses Pseudo-Element ansprechen.
video::-webkit-media-controls {
display:none !important;
}
Dies blendet die nativen Steuerelemente vollständig aus.
Eine weitere Option ist, dass Sie tiefer in den Unterbaum gehen können, um das Pseudo-Element zu finden, das dem inneren und spezifischeren div zugeordnet ist, das die eigentlichen Steuerelemente enthält: Schaltflächen, Schieberegler usw. und dieses ausblenden.
Wenn wir also eine Ebene tiefer gehen, erhalten wir das Pseudo-Element, das dem inneren div zugeordnet ist.
video::-webkit-media-controls-enclosure {
display:none !important;
}
Wenn Sie die Eigenschaft display dieses Pseudo-Elements auf none setzen, werden die nativen Steuerelemente im normalen und im Vollbildmodus vollständig ausgeblendet. Sie können auch sehen, dass dieses Pseudo-Element in Bezug auf den Geltungsbereich (das Video-Element) und das ihm zugeordnete div spezifischer ist: das div, das die eigentlichen Steuerelemente „umgibt“.
Und das ist im Grunde alles, was Sie tun müssen, um die nativen Steuerelemente im Vollbildmodus auszublenden. Einfach, oder?
Benutzerdefinierte Video-Steuerelemente anzeigen
Was die benutzerdefinierten Steuerelemente betrifft, so erschienen sie in meiner Demo immer noch nicht, nachdem ich die nativen ausgeblendet hatte, weil, wie Sie im obigen Screenshot gesehen haben, die User-Agent-Stylesheet einen Wert für z-index für den Vollbildmodus hatte.

Ich habe keine Ahnung, warum die Entwickler diesen Wert gewählt haben, aber es könnte daran liegen, dass dieser Wert, wie Nate Volker in seinem Kommentar unten anmerkte, der Maximalwert für eine vorzeichenbehaftete 32-Bit-Ganzzahl ist, was der Datentyp sein könnte, den die Browserentwickler zur Darstellung von Werten für z-index verwenden. Um sicherzustellen, dass die benutzerdefinierten Steuerelemente sichtbar sind, müssen Sie daher den z-index für die benutzerdefinierten Steuerelemente auf diesen Wert oder höher setzen.
Wenn Sie ihn auf 2147483646 setzen, verschwinden die Steuerelemente im Vollbildmodus unter Firefox und manchmal (ein Bug?) unter Chrome. Der z-index für den Steuerelement-Container sollte also >= 2147483647 sein.
.custom-video-controls {
z-index: 2147483647;
}
Zusammenfassung
Um die nativen Steuerelemente im Vollbildmodus in Browsern, die den Shadow DOM unterstützen, auszublenden, müssen Sie
- das Pseudo-Element, das ihnen zugeordnet ist, ansprechen:
video::-webkit-media-controls-enclosure, das Sie mithilfe der Chrome-Entwicklertools und der Inspektion des Shadow DOM finden können, und dessen Anzeige auf none setzen, und dann Ihre benutzerdefinierten Steuerelemente anzeigen - den z-index Ihrer benutzerdefinierten Steuerelemente auf einen Wert setzen, der höher ist als der von der User-Agent-Stylesheet bereitgestellte z-index.
Und das ist im Grunde alles!
Demo
Siehe den Pen Custom HTML5 Video Controls in Full Screen von Chris Coyier (@chriscoyier) auf CodePen.
Was ist mit anderen Browsern, die den Shadow DOM nicht unterstützen?
Während der Arbeit habe ich die Ergebnisse auch in Firefox getestet. Das Setzen des z-index auf den oben genannten Wert lässt die benutzerdefinierten Steuerelemente auch im Vollbildmodus von Firefox erscheinen, so dass das Anzeigen der Steuerelemente einfach ist. Aber die Shadow-DOM-Lösung funktioniert nicht, da Firefox sie noch nicht unterstützt, sodass die nativen Steuerelemente im Vollbildmodus auch weiterhin erscheinen.
Man kann durchaus ähnliches Verhalten in anderen Browsern erwarten, die den Shadow DOM nicht unterstützen.
Der einzige Weg, den ich gefunden habe, die nativen Steuerelemente in diesen Browsern auszublenden, ist, die nativen Steuerelemente mit den benutzerdefinierten zu überdecken, indem man einfach einfache und grundlegende CSS-Stile verwendet, die auf den Vollbildmodus abzielen, um die benutzerdefinierten Steuerelemente darüber zu positionieren.
Dies blendet die nativen Steuerelemente aus, hat aber auch eine Einschränkung: Die benutzerdefinierten Steuerelemente können keinen transparenten Hintergrund haben, sonst scheinen die nativen Steuerelemente durch.
Es gibt hier noch eine weitere mögliche Lösung. Herr James Edwards bemerkte in seinem Kommentar unten, dass die nativen Steuerelemente im Vollbildmodus auch auf andere Weise ausgeblendet werden können, ohne den Shadow DOM verwenden zu müssen, indem man den Vollbildmodus auf ein Element anwendet, zum Beispiel ein
Weitere Lektüre
- W3C's Shadow DOM Working Draft
- Shadow DOM 101 auf HTML5Rocks
- The Dark Shadow Of The DOM auf SitePoint
- What The Heck Is Shadow DOM von Dimitri Glazkov
Und wenn Sie interessiert sind, können Sie auch sehen, wie Sie die Shadow-DOM-API und HTML <template>s verwenden können, um Ihren eigenen „gekapselten“ Code und HTML-Vorlagen zu erstellen, indem Sie sich diese Präsentation von Peter Gasston über Web Components ansehen, die er auf der diesjährigen CSSConfEU hielt.
Ich liebe es, Sara! Du bist ein Genie.
Ich liebe das Video in der Demo :)
In der Tat – vielen Dank!
2147483647 ist der Maximalwert für eine vorzeichenbehaftete 32-Bit-Ganzzahl, was wahrscheinlich der Datentyp ist, den die Browserentwickler zur Darstellung von z-index-Werten verwenden.
Das ist ein guter Tipp! Danke, Nate! Ich war sehr neugierig darauf. :)
Ich habe einen HTML5-Videoplayer entwickelt, der den Vollbildmodus unterstützt, und ich bin nie auf diese Probleme gestoßen.
Wenn Sie den Vollbildmodus aktivieren, wenden Sie ihn auf das VIDEO-Element an? Wenn ja, ist das das Problem – wenn Sie das VIDEO in ein Container-DIV einpacken und dann den Vollbildmodus auf diesen Container anwenden, funktioniert alles wie erwartet, in allen Browsern, die den Vollbildmodus unterstützen (d. h. aktuelle Versionen von Chrome, Safari, Firefox und Opera).
Hier: http://www.accessibilityoz.com.au/products/ozplayer/
Danke für den Kommentar, James!
In der von mir für diesen Artikel bereitgestellten Demo musste ich den Vollbildmodus auf den Container des Videos anwenden, um die benutzerdefinierten Steuerelemente dort zu positionieren, wo ich sie haben wollte (in Firefox), aber das löste das Problem der nativen Steuerelemente immer noch nicht. Die nativen Steuerelemente waren im Vollbildmodus unter Firefox immer noch da.
Die Anwendung des Vollbildmodus auf den Video-Container funktioniert unter Chrome, ich habe es gerade getestet, aber bei mir funktioniert es nicht unter Firefox. :/
Bearbeitung meines vorherigen Kommentars
Mein Fehler! Es funktioniert *doch* auch unter Firefox! Danke für den Tipp, James. :)
Ich kann Ihre Ergebnisse, James, bestätigen. In meinem Fall habe ich das Video in einem Container und alles andere in einem nachfolgenden Container. Beide Container sind dann wieder eingepackt. Dieser Wrapper wird „im Vollbildmodus“ angezeigt. Die parallelen Container lösten das z-index-Problem, ohne dass ich das Problem jemals bemerkt hätte – und es erfordert keine Shadow DOM-Unterstützung oder das Wissen über alle browserspezifischen Pseudo-Selektoren.
Beste Grüße
2147483647 = 2^31 – 1
Danke für den Beitrag… Ich bin bestenfalls ein Laie… und mache jetzt alles in WordPress…. mein Heiliger Gral ist, wie man die Steuerelemente unter den Videorahmen schiebt. Ist das eine totale Katastrophe oder machbar?
Das *sollte* durch die Vergabe eines negativen unteren Randes an die Steuerelemente möglich sein. Ich habe es nicht ausprobiert, aber es könnte funktionieren.
Die großartige Sara schlägt wieder zu :D
Fantastisch wie immer.
http://www.nilnakliyat.com/ Danke für den Kommentar, James!
FWIW IE11 unterstützt *die* Vollbild-API, mit Präfix (laut Can I use…).
Cool, das bedeutet also, dass die Vollbildfunktion, die auf den Container angewendet wird, in IE11 funktionieren könnte/sollte, aber die Shadow-DOM-Technik könnte funktionieren oder auch nicht, da die Unterstützung für den Shadow DOM in IE11 noch unbekannt ist (auch laut http://caniuse.com/shadowdom).
Schöner Beitrag! Danke!!!
Ich glaube nicht, dass das ein Problem ist, wenn Sie das Container-Element im Vollbildmodus anzeigen.
Dasjenige, das sowohl die Steuerelemente als auch das Video enthält. Dies könnte es tatsächlich einfacher machen, das Video und die Steuerelemente im Vollbildmodus zu gestalten.
Das ist es, was ich gerade tue, da ich auch dabei bin, einen benutzerdefinierten Videoplayer zu entwickeln.
Das ist definitiv ein interessanter Ansatz, aber nicht sehr robust. Die Demo funktioniert in Chrome richtig, aber in der neuesten Safari-Beta sind die benutzerdefinierten Steuerelemente zusammen mit den nativen vorhanden.
Wie einige andere Kommentatoren sagten, ist die bessere Lösung, das Wrapper-Element im Vollbildmodus anzuzeigen. Es hat auch den Vorteil, dass es in mehr Browsern unterstützt wird. Ich habe eine Bibliothek geschrieben, die wir im Vimeo-Player verwenden, um die Handhabung all der Variationen und Bugs (es gibt einige, die insbesondere iframes betreffen) etwas zu erleichtern.
Wahooo…! Tolle Arbeit von Sara, sehr geschätzt
Endlich kann ich mein Problem mit der Breite der Video-Steuerelemente überwinden, danke an den Mitwirkenden! :)
Großartiger Beitrag… Danke an Sara und dich !!
Erstaunlicher Artikel :)
Ich habe diese Lösung in meinen Player integriert. Leider zeigt Firefox das benutzerdefinierte Steuerelement nicht in voller Breite an :(
Demo http://www.athimannil.com/player/