Hier ist eine Idee! Lassen Sie uns ein HTML-<video> so abspielen, dass es sich *im* Inneren der Form von Buchstaben befindet. Ähnlich wie bei „Knockout Text“, nur dass statt eines Bildes dahinter ein Video ist. Eine Live-Demo erklärt es besser
Wenn Sie Safari verwenden, müssen Sie diesen Kommentar beachten, damit alles richtig funktioniert.
Ein Hauptziel ist hier, dies responsiv zu entwickeln. Die Idee ist nicht nur, die Videogröße anzupassen, um sie in den übergeordneten Container einzupassen (wie es Videos generell tun), sondern auch die Textgröße beizubehalten und so das Größenverhältnis zwischen Schrift und darunterliegendem Video zu wahren.
Wir erreichen dies durch die CSS-Eigenschaft clip-path, um das Video gegen einen SVG-Pfad zu schneiden, der in einem -Element definiert ist.
Zuerst behandeln wir das Kernkonzept. Dann fügen wir etwas Augenschmaus hinzu, indem wir einige weitere Features ergänzen und sie mit ein paar zusätzlichen Demos demonstrieren.
Einrichten des Videos in HTML
Beginnen wir mit dem Video-Markup. Innerhalb des <video>-Tags geben wir die URLs für die WebM- und MP4-Versionen des Videos an, um eine breite Palette von Browsern zu unterstützen.
<video>
<source src="/video/mt-baker.webm" type="video/webm">
<source src="/video/mt-baker.mp4" type="video/mp4">
</video>
Dann fügen wir einige Attribute hinzu, um das Wiedergabeverhalten des Videos anzupassen.
<video loop autoplay muted playsinline>
<source src="/video/mt-baker.webm" type="video/webm">
<source src="/video/mt-baker.mp4" type="video/mp4">
</video>
- Das Attribut
looplässt das Video endlos spielen. - Die Attribute
autoplayundmutedwerden verwendet, um die automatische Videowiedergabe beim Laden der Seite auf allen Geräten zu ermöglichen und sicherzustellen, dass es ohne Ton abgespielt wird. - Das Attribut
playsinlineversucht, die Vollbild-Erweiterung des Videos auf einigen Mobilgeräten zu deaktivieren.
Dann wird ein Container um das <video>-Element gewickelt. Dies wird nützlich sein, wenn wir die grundlegende Demo mit einigen visuellen Effekten aufpeppen.
Hier ist das vollständige Markup.
<div class="video-container">
<video loop autoplay muted playsinline>
<source src="/video/mt-baker.webm" type="video/webm">
<source src="/video/mt-baker.mp4" type="video/mp4">
</video>
</div>
Das grundlegende CSS zum Positionieren und Skalieren des Videos
Hier ist die Hauptaufgabe, das Video responsiv zu machen. Es muss sich skalieren, die Breite seines übergeordneten Containers ausfüllen und sein intrinsisches Seitenverhältnis beibehalten.
.video-container video {
display: block;
width: 100%;
}
Nachdem das Video als Block-Element mit display: block formatiert wurde, macht die Zuweisung eines Wertes von 100 % zu seiner Breite es so groß wie sein Container. Und das ist alles, was wir brauchen, denn der ursprüngliche auto-Wert der height-Eigenschaft und das intrinsische Seitenverhältnis des Videos lassen es gleichmäßig skalieren, ohne Verzerrung.
In der ursprünglichen Demo habe ich das Video mehrmals im Container wiederholt, um dieses responsive Verhalten zu testen. Hier ist das CSS, das ich verwende, um die Responsivität jedes Videos bei unterschiedlichen Breiten zu testen.
.video-container {
margin: 40px auto;
outline: 1px solid #dadada;
&:nth-of-type(1) { width: 25%; } /* first video instance, and so on */
&:nth-of-type(2) { width: 50%; }
&:nth-of-type(3) { width: 75%; }
&:nth-of-type(4) { width: 100%; }
}

Die outline, die auf den Containern gesetzt ist, hilft uns, den Speicherort und die Größe der Videos zu visualisieren, wenn sie geschnitten werden. Apropos…
Das Video in CSS ausschneiden
Dank der CSS-Eigenschaft clip-path können wir einen Bereich eines Elements definieren, der anstelle des gesamten Elements angezeigt werden soll – und das mit einer einzigen Zeile.
video {
clip-path: url(#clip-00);
}
Mit der Funktion url() geben wir die ID des SVG clipPath-Elements an, in dem der Clipping-Text definiert ist.
Beachten Sie, dass, obwohl die sichtbare Geometrie des Videos durch das Clipping verändert wird, das Videoelement für den Browser immer noch eine rechteckige Box ist, sodass das Seitenlayout dasselbe ist, als ob das Clipping nicht verwendet würde. Das ist Teil der Schönheit des Clipping, und wenn Sie neu in diesem Konzept sind, dann schauen Sie sich unbedingt Sarahs Erklärung dazu an.
Nun ist die Herausforderung, diesen Clipping-Pfad tatsächlich zu erstellen!
Erstellen des SVG clipPath-Elements
Ich werde das Textdesign erstellen, die Bearbeitung vornehmen und dann die Arbeit in Inkscape exportieren. Ähnliche Schritte könnten mit anderen Vektoreditoren durchgeführt werden. Melden Sie sich gerne in den Kommentaren mit Ihren Erfahrungen.
Der erste Schritt ist, sich das Seitenverhältnis des Videos zu notieren, also sein Verhältnis von Breite:Höhe.
Erstellen Sie als Nächstes ein Dokument mit der gleichen Größe wie das Video oder einfach mit dem gleichen Seitenverhältnis. Wenn Ihr Video also 1000px breit und 500px hoch ist, können Sie dies als Dokumentgröße verwenden oder etwas mit einem Verhältnis von 2:1. Dies dient als Platzhalter für das Video, stellen Sie also sicher, dass die Dokumentränder sichtbar sind. Entfernen Sie auch die Standardebene, die vom Programm erstellt wird, da dies den von SVG generierten Code vereinfacht und die Erstellung unnötiger Gruppenelemente vermeidet.

Wählen Sie das Textwerkzeug, wählen Sie eine schöne fette und dicke Schriftart, geben Sie den Text ein und dehnen Sie ihn, um das Dokumentrechteck nach Belieben abzudecken.

Wenn wir uns nun den von Inkscape generierten Code ansehen, sehen wir etwas wie das hier.
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:1147.68029785px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="23.404421"
y="939.04187"
id="text3336"
sodipodi:linespacing="125%"
transform="scale(0.8988993,1.1124717)"
>
<tspan
sodipodi:role="line"
id="tspan3338"
x="23.404421"
y="939.04187"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-family:Impact;-inkscape-font-specification:'Impact Condensed'"
>
TEXT
</tspan>
</text>
Das ist etwas unhandlich, also wandeln wir das SVG--Element in einen Pfad um.
<g
transform="scale(0.8988993,1.1124717)"
style="font-style:normal;font-weight:normal;font-size:1147.68029785px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
id="text3336"
>
<path
d="m 545.68862,31.769213 0,181.566607 -140.09769,0 0,725.70605 -235.92452,0 0,-725.70605 -139.5373,0 0,-181.566607 515.55951,0 z"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-family:Impact;-inkscape-font-specification:'Impact Condensed'"
id="path3348" />
<path
d="m 599.48616,31.769213 393.39432,0 0,181.566607 -157.46981,0 0,172.03997 147.38277,0 0,172.60036 -147.38277,0 0,199.49911 173.16073,0 0,181.56661 -409.08524,0 0,-907.272657 z"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-family:Impact;-inkscape-font-specification:'Impact Condensed'"
id="path3350" />
<path
d="M 1554.9524,31.769213 1472.575,433.009 l 124.4067,506.03287 -218.5524,0 q -39.2273,-135.61457 -71.73,-330.07016 -8.9662,85.73978 -24.6572,182.127 l -22.4156,147.94316 -229.7602,0 85.1794,-506.03287 -85.1794,-401.239787 228.079,0 q 6.1643,37.546181 24.6572,124.967137 14.5702,66.68651 24.0968,122.16519 l 50.4352,-247.132327 197.8179,0 z"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-family:Impact;-inkscape-font-specification:'Impact Condensed'"
id="path3352" />
<path
d="m 2105.8165,31.769213 0,181.566607 -140.0976,0 0,725.70605 -235.9246,0 0,-725.70605 -139.5373,0 0,-181.566607 515.5595,0 z"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-family:Impact;-inkscape-font-specification:'Impact Condensed'"
id="path3354" />
</g>
Nun haben wir eine Gruppe, die ein Pfadelement für jeden Buchstaben des Textes enthält. Wenn wir es aufheben, bleiben diese Pfade auf der Wurzelebene. Dieser Schritt entfernt nicht nur die unnötige Gruppe, sondern ändert auch die Koordinaten der Pfadelemente, um den auf die entfernte übergeordnete Gruppe angewendeten Transform zu berücksichtigen. Nach diesem Schritt gibt es keine Transform-Attribute mehr im SVG.
<path
inkscape:connector-curvature="0"
id="path3348"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:medium;line-height:125%;font-family:Impact;-inkscape-font-specification:'Impact Condensed';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 490.51912,35.34235 0,201.98771 -125.93372,0 0,807.32744 -212.07238,0 0,-807.32744 -125.429984,0 0,-201.98771 463.436084,0 z" />
<path
inkscape:connector-curvature="0"
id="path3350"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:medium;line-height:125%;font-family:Impact;-inkscape-font-specification:'Impact Condensed';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 538.87769,35.34235 353.62188,0 0,201.98771 -141.5495,0 0,191.3896 132.48227,0 0,192.01302 -132.48227,0 0,221.93711 155.65406,0 0,201.98771 -367.72644,0 0,-1009.31515 z" />
<path
inkscape:connector-curvature="0"
id="path3352"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:medium;line-height:125%;font-family:Impact;-inkscape-font-specification:'Impact Condensed';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 1397.7456,35.34235 -74.049,446.36791 111.8291,562.94724 -196.4566,0 q -35.2614,-150.86737 -64.478,-367.19371 -8.0597,95.38308 -22.1644,202.61114 l -20.1493,164.58257 -206.5313,0 76.5677,-562.94724 -76.5677,-446.36791 205.02,0 q 5.5411,41.769064 22.1644,139.0224 13.0971,74.18686 21.6606,135.90532 l 45.3362,-274.92772 177.8183,0 z" />
<path
inkscape:connector-curvature="0"
id="path3354"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:medium;line-height:125%;font-family:Impact;-inkscape-font-specification:'Impact Condensed';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 1892.917,35.34235 0,201.98771 -125.9337,0 0,807.32744 -212.0724,0 0,-807.32744 -125.43,0 0,-201.98771 463.4361,0 z" />
Diese hässlichen Style-Attribute sind immer noch da, aber das spielt keine Rolle, da wir sie nicht verwenden werden.
Wir sind mit Inkscape fertig, also können wir das SVG-Dokument speichern und es in unserem bevorzugten Code-Editor öffnen.
Das Speichern von SVG-Dateien aus einer Illustrationsanwendung ist eine eigene Kunstform. Hier sind einige gängige Tipps und übliche Einstellungen für Adobe Illustrator und ein Vergleich von SVG-Exporten aus Illustrator, Sketch und Figma.
Fügen Sie auf der HTML-Seite, auf der das Video abgespielt wird, ein Inline-SVG-Element ein. Dieses wird den Clipping-Pfad enthalten.
<svg class="clipping-paths">
<defs>
</defs>
</svg>
Wir möchten nicht, dass dieses Container-Element das Seitenlayout beeinflusst, also.
.clipping-paths {
width: 0;
height: 0;
position: absolute;
}
Fügen Sie dem Container-SVG ein neues clipPath-Element mit einer geeigneten ID hinzu, um es in der clip-path-Eigenschaft zu identifizieren, wie bereits gesehen.
<svg class="clipping-paths">
<defs>
<clipPath id="clip-00"></clipPath>
<clipPath id="clip-01"></clipPath>
...
</defs>
</svg>
Wie im obigen Ausschnitt gezeigt, können bei Bedarf mehrere Clipping-Pfade hinzugefügt werden.
Nun müssen wir dem clipPath-Attribut clipPathUnits den Wert objectBoundingBox zuweisen.
<clipPath id="clip-00" clipPathUnits="objectBoundingBox"></clipPath>
Dies ist eine der wichtigsten Aufgaben für einen responsiven Ausschnitt. Wir teilen dem Browser mit, welches Koordinatensystem für die numerischen Werte in den d-Attributen der Pfade verwendet werden soll, die dem clipPath-Element angehängt werden.
Der Standardwert für das Attribut clipPathUnits ist userSpaceOnUse. Gemäß der Spezifikation bedeutet dies, dass:
…die Inhalte des
clipPath-Elements Werte im aktuellen Benutzerkoordinatensystem darstellen, das zum Zeitpunkt der Referenzierung des (clipPath)-Elements (d. h. des Benutzerkoordinatensystems für das Element, das dasclipPath-Element über die clip-path-Eigenschaft referenziert) gültig ist.
Stattdessen werden bei Verwendung des anderen verfügbaren Werts für clipPathUnits, objectBoundingBox, die Koordinatenwerte und Längen, die im clipPath-Inhalt angegeben sind, als Bruchwerte im Bereich [0,1] betrachtet, relativ zur Bounding Box des beschnittenen Elements. Wenn beispielsweise ein grafisches Primitiv im clipPath die Koordinaten (0,0), (1,0), (1,1), (0,1) und (0,5,0,5) referenzieren würde, würden diese Punkte das obere linke, obere rechte, untere rechte, untere linke Eck und das Zentrum des Videos darstellen, unabhängig von der tatsächlichen Größe des Videos auf dem Bildschirm. Dieses Verhalten ermöglicht es dem Text-Ausschnitt, sich auf die gleiche Weise zu skalieren wie das darunterliegende Video.
Nachdem alle Transformationen aus der SVG-Datei in Inkscape entfernt wurden, liegen alle numerischen Werte der Pfadelemente im Dokumentbereich. Um sie in das für objectBoundingBox erforderliche Intervall [0,1] zu übertragen, genügt es, diese numerischen Werte durch die Dokumentgröße zu dividieren. Die x-Koordinaten werden durch die Dokumentbreite und die y-Koordinaten durch die Dokumenthöhe geteilt.
Um diese Division durchzuführen, kann eine Skalierung mit dem SVG-Attribut transform verwendet werden.
<clipPath id="clip-00" clipPathUnits="objectBoundingBox" transform="scale(0.0005208333333333333, 0.000925925925925926)">
Die horizontale Skalierung muss der Kehrwert der Dokumentbreite sein, während die vertikale Skalierung der Kehrwert der Dokumenthöhe sein muss. In unserem Fall, da das Dokument exakt die gleiche Größe wie das Video hat, also 1920 X 1080, erhalten wir die beiden Faktoren 1 / 1920 = 0.0005208333333333333 und 1 / 1080 = 0.000925925925925926.
Der letzte Schritt in diesem Workflow ist das Kopieren der -Elemente aus der von Inkscape generierten Datei in das clipPath-Element, was zu etwas wie dem hier führt.
<clipPath id="clip-00" clipPathUnits="objectBoundingBox" transform="scale(0.0005208333333333333, 0.000925925925925926)">
<path d="m 341.4087,58.040727 0,951.927273 -112.60986,0 -66.8335,-432.74767 0,432.74767 -107.42188,0 0,-951.927273 107.42188,0 72.02149,428.631863 0,-428.631863 107.42187,0 z" />
...
<path d="m 1642.6782,58.040727 214.2334,0 0,190.503053 -85.7544,0 0,180.50751 80.2613,0 0,181.09549 -80.2613,0 0,209.31816 94.2994,0 0,190.50306 -222.7784,0 0,-951.927273 z" />
</clipPath>
Zur Wiederholung: Wir haben nur das d-Attribut der Pfade kopiert und alles andere, was von Inkscape generiert wurde, verworfen.
Alles zusammenfügen
Und da haben wir es, wenn wir die obigen Ausschnitte mit etwas mehr Code zusammenfügen (siehe Pen-Quelle für Details), erhalten wir die erste grundlegende Demo.
Weitere Beispiele
Wir können den obigen Workflow wiederverwenden, um weitere Ausschnitte zu erstellen, wie in der zweiten Demo hier.
Das letzte Beispiel ist bemerkenswert, da es das Negative des in der ersten Demo verwendeten Textes ist; das heißt, die inneren und äußeren Regionen, die durch die Pfade begrenzt werden, wurden vertauscht. Der weiße Text, den wir sehen, ist also ein Loch, durch das die Hintergrundfarbe des Seitenkörpers sichtbar ist. Dieser negative Ausschnitt wurde aus dem Original mit einer Differenz-Pfadoperation in Inkscape abgeleitet.
Hinzufügen von Hintergrundfarben
Aufbauend auf der Basis-Demo können wir dem Text-Ausschnitt eine Farbe hinzufügen, indem wir dem Video-Container eine background-color zuweisen, da dieser Wrapper überall sichtbar ist, wo das Video ausgeschnitten ist.
.video-container {
// ...
&:nth-of-type(1) { background: #c6c7c5; }
&:nth-of-type(2) { background: #dcf3ff; }
&:nth-of-type(3) { background: #a2d2df; }
&:nth-of-type(4) { background: #406e8d; }
&:nth-of-type(5) { background: linear-gradient(180deg, #bdc3c2, #2d5d89); }
}
Das Ergebnis kann in der dritten Demo gesehen werden.
Hinzufügen von Tönung
Wie wäre es mit einer Tönung des Videos? Das können wir mit einem Pseudo-Element und CSS-Blendmodi machen.
.video-container {
/* ... */
position: relative;
}
.video-container::after {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
clip-path: url(#clip-00);
}
.video-container:nth-of-type(1) {
background: #406e8d;
}
.video-container:nth-of-type(1)::after {
background-color: #3f51b5;
mix-blend-mode: screen;
}
Das Pseudo-Element ::after des Video-Wrappers wird absolut über dem Video positioniert, bedeckt es vollständig und wird dann mit demselben Pfad beschnitten wie das Video. Auf diese Weise können verschiedene Farben für Hintergrund und Tönung verwendet werden.
Schließlich, nachdem der gewünschte Tönungsfarbe dem Pseudo-Element zugewiesen wurde, können wir mit der Eigenschaft mix-blend-mode einen der verfügbaren Mischmodi auswählen, um den gewünschten Effekt zu erzielen.
Browser-Unterstützung
Zum Zeitpunkt des Schreibens unterstützen fast alle neuesten Versionen von Desktop- und mobilen Browsern die CSS-Eigenschaft clip-path. Die präfixte Version, -webkit-clip-path, muss auf WebKit-basierten User Agents wie Safari und Samsung Internet verwendet werden.
Diese Browser-Support-Daten stammen von Caniuse, das mehr Details enthält. Eine Zahl gibt an, dass der Browser die Funktion ab dieser Version unterstützt.
Desktop
| Chrome | Firefox | IE | Edge | Safari |
|---|---|---|---|---|
| 130 | 54 | Nein | 127 | TP |
Mobil / Tablet
| Android Chrome | Android Firefox | Android | iOS Safari |
|---|---|---|---|
| 127 | 127 | 127 | 18.0 |
Leider gibt es eine Ausnahme bei Microsoft-Browsern. Im Internet Explorer gibt es definitiv keine Unterstützung, und bei Edge ist die Funktion in Entwicklung. Bitte stimmen Sie dafür auf der Microsoft Developer Feedback-Seite!
Natürlich wird für die letzte Demo ein Browser benötigt, der CSS-Blendmodi unterstützt. In diesem Fall ist die Unterstützung breiter, da diese Funktion sogar von Edge implementiert wird.
Diese Browser-Supportdaten stammen von Caniuse, wo weitere Details zu finden sind. Eine Zahl zeigt an, dass der Browser die Funktion ab dieser Version unterstützt.
Desktop
| Chrome | Firefox | IE | Edge | Safari |
|---|---|---|---|---|
| 30 | 20 | Nein | 13 | 6.1 |
Mobil / Tablet
| Android Chrome | Android Firefox | Android | iOS Safari |
|---|---|---|---|
| 127 | 127 | 4.4 | 7.0-7.1 |
Referenzen und Credits
Eric Meyer schreibt über die Skalierung von SVG-Clipping-Pfaden für die Verwendung in CSS, die Verwendung des Werts objectBoundingBox für das Attribut clipPathUnits und die Skalierungstransformation. Das war eine große Inspiration für diesen Beitrag.
Dank Coverr für das Video, das in diesen Demos verwendet wurde.
Das ist erstaunlich! Wirklich cool, Giulio!
Also... keiner der CodePens funktioniert auf iOS 11.3 in der neuesten Version von Chrome oder Safari. :/
Danke für Ihr Feedback!
Es scheint, dass WebKit einige Schwierigkeiten hat, HTML-Elemente gegen einen Pfad auszuschneiden, der mit einem SVG-ClipPath-Element definiert ist. Ich stelle ein paar Pens zusammen, um die Probleme zu zeigen. Bleiben Sie dran!
Die letzten 2 zeigen das Video nicht in Chrome 64bit Linux.
WebKit (getestet auf iOS Safari 11.2.6) hat einige Probleme beim Ausschneiden eines
<video>, selbst mit dem einfachsten<clipPath>, nichts wird gerendert.Auch https://lab.iamvdo.me/css-svg-masks/ enthält mehrere interessante Tests (nicht mit Videos).
@jgarcianewemage
Könnten Sie mir sagen, was auf dem dritten Pen (Hintergrundfarben) passiert?
Welche Chrome-Version?
Haben Sie auch diese Tests ausprobiert?
Update: Der grundlegende Pen funktioniert auf iOS Safari, wenn das Video in einem DIV eingepackt ist und die
clip-pathauf diesen Container angewendet wird: https://codepen.io/mgiulio/pen/bMLWWw?editors=0100Allerdings ist der Text-Ausschnitt nicht perfekt transformiert, es gibt eine leichte Verschiebung nach oben, wie der ungleichmäßige violette Rand zeigt. Das gleiche Problem tritt auf, wenn ein Bild anstelle eines Videos verwendet wird.