Component: Media Overlay

Implementation Notes

  • To enable opening the media in a new tab, the preview have to be linked to the original source, i.e., to the video or audio file, YouTube video, or high-resolution image.
  • The href value of this link is used as the source for the enlarged media by default.
  • When the link is marked with the download attribute, a CTA for downloading the source file is displayed in the overlay (only works with image files).
  • Generally, the file from the link is displayed in the overlay. However, since the link can also be used for downloading oversized files or files in formats not suitable for browser display (e.g., Photoshop files), a file for display in the zoom can be defined via the data attribute data-zoom.
  • If neither a link nor a data attribute data-zoom is defined, the preview is displayed in the zoom.

Optimum image size

Preview

See Component Media Gallery

Zoom

  • Desktop: widest side 1600 pixels
  • Mobile: widest side 640 pixels
<!-- Default -->


<!-- Vue Component -->
<script type="text/x-template" id="mediaOverlay-overlay-template">

    <div class="mediaOverlay" :data-visible="isVisible == true">

        <nav class="mediaOverlay-nav">
            <button class="mediaOverlay-close" data-action="close"><span>Schließen</span></button>
        </nav>

        <div class="mediaOverlay-header">
            <div v-if="asset.description" class="mediaOverlay-description">
                <span v-html="asset.description.caption" class="mediaOverlay-caption"></span> <span v-html="asset.description.copyright" class="mediaOverlay-copyright"></span>
            </div>

            <div v-if="asset.cta.url" class="mediaOverlay-cta">
                <a :href="asset.cta.url" class="button" download=""><svg class="icon is-download-simple"><use xlink:href="/icons/icons-bold.svg#icon--download-simple"></use></svg><span class="button-label">Herunterladen</span></a>
            </div>
        </div>

        <div class="mediaOverlay-content" :data-type="asset.type">

            <!-- Image -->
            <figure v-if="asset.image && asset.image.src" class="mediaOverlay-figure">
                <img class="figure-image" :src="asset.image.src" :alt="asset.image.alt" :style="{ 'background-image': 'url(' + asset.image.lowres + ')' }" data-trigger="">
            </figure>

            <!-- Video -->
            <div v-if="asset.video && asset.video.src" class="mediaOverlay-figure">
                <figure class="videoPlayer">
                    <div class="videoPlayer-video">
                        <video :poster="asset.video.poster" class="video" controls>
                            <source :src="asset.video.src" :type="asset.video.type">
                        </video>
                    </div>
                </figure>
            </div>

            <!-- YouTube video -->
            <figure v-if="asset.video && asset.video.isYouTube" class="mediaOverlay-figure is-youtube">
                <iframe :src="'https://www.youtube-nocookie.com/embed/' + asset.video.id + '?rel=0'"  width="1280" height="720" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
            </figure>

            <!-- Audio -->
            <div v-if="asset.audio && asset.audio.src" class="mediaOverlay-figure">
                <figure class="audioPlayer">
                    <div v-if="asset.audio.poster" class="audioPlayer-poster" aria-hidden="true">
                        <img :src="asset.audio.poster" alt=""/>
                    </div>
                    <div class="audioPlayer-audio">
                        <audio :src="asset.audio.src" class="audio" controls></audio>
                    </div>
                </figure>
            </div>

        </div>

    </div>

</script>

<div v-cloak id="mediaOverlay">
    <overlay></overlay>
</div>

<!-- Blocked Video -->
<div id="mediaOverlay" data-v-app="" style="transition-duration: 150ms;">
    <div class="mediaOverlay" data-visible="true" style="--aspect-ratio: 1504/846;">
        <nav class="mediaOverlay-nav"><button class="mediaOverlay-close" data-action="close" data-active="true" data-trigger=""><span>Schließen</span></button></nav>
        <div class="mediaOverlay-header">
            <div class="mediaOverlay-description"><span class="mediaOverlay-caption">Ich bin der Titel des Mediums</span> <span class="mediaOverlay-copyright"></span></div>
        </div>
        <div class="mediaOverlay-content" data-type="video">
            <figure class="mediaOverlay-figure is-youtube">
                <iframe src="https://cloud.ccm19.de/x-content-blocked.html?apiKey=d25f730e279e287e431f83c2f4b78964c741fa1266190ca5&domain=664f6d5790e20920600adc62&gen=2&theme=664f6d5790e20920600adc71&lang=de_DE&v=1733243400&url=https%3A%2F%2Fwww.youtube-nocookie.com%2Fembed%2F2eRWscBHHAI%3Frel%3D0&embedding=674eb432b73797f4e20c9c97" width="1280" height="720" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
                <div class="ccm--consent-switch"><input id="ccm--consent-switch-e3ad1c8910caef19" type="checkbox"><label for="ccm--consent-switch-e3ad1c8910caef19">Inhalt für "YouTube Video" zulassen</label><a href="javascript:">(Details zum Anbieter)</a></div>
            </figure>
        </div>
    </div>
</div>

<!-- Demo Only -->
<script type="text/x-template" id="mediaOverlay-overlay-template">

    <div class="mediaOverlay" :data-visible="isVisible == true">

        <nav class="mediaOverlay-nav">
            <button class="mediaOverlay-close" data-action="close"><span>Schließen</span></button>
        </nav>

        <div class="mediaOverlay-header">
            <div v-if="asset.description" class="mediaOverlay-description">
                <span v-html="asset.description.caption" class="mediaOverlay-caption"></span> <span v-html="asset.description.copyright" class="mediaOverlay-copyright"></span>
            </div>

            <div v-if="asset.cta.url" class="mediaOverlay-cta">
                <a :href="asset.cta.url" class="button" download=""><svg class="icon is-download-simple"><use xlink:href="/icons/icons-bold.svg#icon--download-simple"></use></svg><span class="button-label">Herunterladen</span></a>
            </div>
        </div>

        <div class="mediaOverlay-content" :data-type="asset.type">

            <!-- Image -->
            <figure v-if="asset.image && asset.image.src" class="mediaOverlay-figure">
                <img class="figure-image" :src="asset.image.src" :alt="asset.image.alt" :style="{ 'background-image': 'url(' + asset.image.lowres + ')' }" data-trigger="">
            </figure>

            <!-- Video -->
            <div v-if="asset.video && asset.video.src" class="mediaOverlay-figure">
                <figure class="videoPlayer">
                    <div class="videoPlayer-video">
                        <video :poster="asset.video.poster" class="video" controls>
                            <source :src="asset.video.src" :type="asset.video.type">
                        </video>
                    </div>
                </figure>
            </div>

            <!-- YouTube video -->
            <figure v-if="asset.video && asset.video.isYouTube" class="mediaOverlay-figure is-youtube">
                <iframe :src="'https://www.youtube-nocookie.com/embed/' + asset.video.id + '?rel=0'"  width="1280" height="720" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
            </figure>

            <!-- Audio -->
            <div v-if="asset.audio && asset.audio.src" class="mediaOverlay-figure">
                <figure class="audioPlayer">
                    <div v-if="asset.audio.poster" class="audioPlayer-poster" aria-hidden="true">
                        <img :src="asset.audio.poster" alt=""/>
                    </div>
                    <div class="audioPlayer-audio">
                        <audio :src="asset.audio.src" class="audio" controls></audio>
                    </div>
                </figure>
            </div>

        </div>

    </div>

</script>

<div v-cloak id="mediaOverlay">
    <overlay></overlay>
</div>

<div style="min-height: 100vh;"><!-- Force displaying scrollbar -->

    <div class="doc-section">

        <h2 class="doc-section-title">Galerie mit Bildern</h2>

        <div class="doc-variant-samples">

            <div class="mediaGallery">

                <ul class="mediaGallery-items">

                    <li class="mediaGallery-item" data-type="image" data-media-overlay data-action="open" data-trigger-selector=".mediaGallery-link">

                        <figure class="mediaGallery-preview" style="background-image: url(../../images/placeholder/dummy-image-640w.jpg);">
                            <a class="mediaGallery-link" href="../../images/placeholder/dummy-image-full-size.jpg" download target="_blank">
                                <img src="../../images/placeholder/dummy-image-640w.jpg" data-zoom="../../images/placeholder/dummy-image.jpg" alt="Alternative Bildbeschreibung" />
                            </a>

                            <figcaption class="mediaGallery-caption"><span>Ich bin der Titel des Mediums</span><small class="mediaGallery-copyright">Foto von <a class="link" href="https://unsplash.com/de/@ssergiomedinaa?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Sergio Medina</a></small></figcaption>
                        </figure>

                    </li>
                    <li class="mediaGallery-item" data-type="image" data-media-overlay data-action="open" data-trigger-selector=".mediaGallery-link">

                        <figure class="mediaGallery-preview" style="background-image: url(../../images/placeholder/dummy-image-640w.jpg);">
                            <a class="mediaGallery-link" href="../../images/placeholder/dummy-image-full-size.jpg" target="_blank">
                                <img src="../../images/placeholder/dummy-image-640w.jpg" data-zoom="../../images/placeholder/dummy-image.jpg" alt="Alternative Bildbeschreibung" />
                            </a>

                            <figcaption class="mediaGallery-caption"><span>Overlay ohne Download</span><small class="mediaGallery-copyright">Foto von <a class="link" href="https://unsplash.com/de/@ssergiomedinaa?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Sergio Medina</a></small></figcaption>
                        </figure>

                    </li>
                    <li class="mediaGallery-item" data-type="image" data-media-overlay data-action="open" data-trigger-selector=".mediaGallery-link">

                        <figure class="mediaGallery-preview" style="background-image: url(https://picsum.photos/id/18/480/720);">
                            <a class="mediaGallery-link" href="https://picsum.photos/id/18/1120/1680" download target="_blank">
                                <img src="https://picsum.photos/id/18/480/720" alt="Alternative Bildbeschreibung" />
                            </a>

                            <figcaption class="mediaGallery-caption"><span>Ich bin der Titel des Mediums</span></figcaption>
                        </figure>

                    </li>
                    <li class="mediaGallery-item" data-type="image" data-media-overlay data-action="open" data-trigger-selector=".mediaGallery-link">

                        <figure class="mediaGallery-preview" style="background-image: url(https://picsum.photos/id/193/720/360);">
                            <a class="mediaGallery-link" href="https://picsum.photos/id/193/1680/840" download target="_blank">
                                <img src="https://picsum.photos/id/193/720/360" alt="Alternative Bildbeschreibung" />
                            </a>

                            <figcaption class="mediaGallery-caption"><span>Ich bin der Titel des Mediums</span></figcaption>
                        </figure>

                    </li>

                </ul>

            </div>

        </div>

    </div>
    <div class="doc-section">

        <h2 class="doc-section-title">Galerie mit Video- und Audiodateien</h2>

        <div class="doc-variant-samples">

            <div class="mediaGallery">

                <ul class="mediaGallery-items">

                    <li class="mediaGallery-item" data-type="video" data-media-overlay data-action="open" data-trigger-selector=".mediaGallery-link">

                        <figure class="mediaGallery-preview" style="background-image: url(../../videos/placeholder/dummy-video.jpg);">
                            <a class="mediaGallery-link" href="../../videos/placeholder/dummy-video.mp4" target="_blank">
                                <img src="../../videos/placeholder/dummy-video.jpg" alt="Alternative Beschreibung des Videos" />
                            </a>

                            <figcaption class="mediaGallery-caption"><span>Ich bin der Titel des Mediums</span><small class="mediaGallery-copyright">Video von <a class="link" href="https://pixabay.com/de/videos/gelb-fl%C3%BCssig-farbe-raum-27803/">Pixabay</a></small></figcaption>
                        </figure>

                    </li>
                    <li class="mediaGallery-item" data-type="video" data-media-overlay data-action="open" data-trigger-selector=".mediaGallery-link">

                        <figure class="mediaGallery-preview" style="background-image: url(https://img.youtube.com/vi/kg2fwlFsZss/maxresdefault.jpg);">
                            <a class="mediaGallery-link" href="https://www.youtube-nocookie.com/watch?v&#x3D;kg2fwlFsZss" target="_blank">
                                <img src="https://img.youtube.com/vi/kg2fwlFsZss/maxresdefault.jpg" alt="Alternative Beschreibung des Videos" />
                            </a>

                            <figcaption class="mediaGallery-caption"><span>Ich bin der Titel des Mediums</span></figcaption>
                        </figure>

                    </li>
                    <li class="mediaGallery-item" data-type="audio" data-media-overlay data-action="open" data-trigger-selector=".mediaGallery-link">

                        <figure class="mediaGallery-preview" style="background-image: url(../../audios/placeholder/dummy-audio-poster.jpg);">
                            <a class="mediaGallery-link" href="../../audios/placeholder/dummy-audio.mp3" target="_blank">
                                <img src="../../audios/placeholder/dummy-audio-poster.jpg" alt="Alternative Beschreibung des Tons" />
                            </a>

                            <figcaption class="mediaGallery-caption"><span>Ich bin der Titel des Mediums</span><small class="mediaGallery-copyright">Audio von <a class="link" href="https://pixabay.com/sound-effects/birds-chirping-ambiance-26052/">Pixabay</a></small></figcaption>
                        </figure>

                    </li>
                    <li class="mediaGallery-item" data-type="audio" data-media-overlay data-action="open" data-trigger-selector=".mediaGallery-link">

                        <figure class="mediaGallery-preview">
                            <a class="mediaGallery-link" href="../../audios/placeholder/dummy-audio.mp3" target="_blank">
                            </a>

                            <figcaption class="mediaGallery-caption"><span>Audiodatei ohne Vorschau</span></figcaption>
                        </figure>

                    </li>

                </ul>

            </div>

        </div>

    </div>
    <div class="doc-section">

        <h2 class="doc-section-title">Video</h2>

        <div class="doc-variant-samples">

            <div data-media-overlay data-action="open" data-trigger-selector=".figure a" data-type="video">
                <figure class="figure" style="">

                    <a href="../../videos/placeholder/dummy-video.mp4" target="_blank">
                        <img class="figure-image" src="../../videos/placeholder/dummy-video.jpg" alt="Alternative Bildbeschreibung" />

                    </a>

                    <figcaption class="figure-caption"><span>Selfies fixie next level trust fund jean shorts photo booth raw denim butcher mixtape ethical mustache.</span><small class="figure-copyright">Foto von <a class="link" href="https://unsplash.com/de/@ssergiomedinaa?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Sergio Medina</a></small></figcaption>

                </figure>

            </div>

        </div>

    </div>
    <div class="doc-section">

        <h2 class="doc-section-title">Youtube Video</h2>

        <div class="doc-variant-samples">

            <div data-media-overlay data-action="open" data-trigger-selector=".figure a" data-type="video">
                <figure class="figure" style="">

                    <a href="https://www.youtube-nocookie.com/watch?v&#x3D;kg2fwlFsZss" target="_blank">
                        <img class="figure-image" src="https://img.youtube.com/vi/kg2fwlFsZss/maxresdefault.jpg" alt="Alternative Bildbeschreibung" />

                    </a>

                    <figcaption class="figure-caption"><span>Selfies fixie next level trust fund jean shorts photo booth raw denim butcher mixtape ethical mustache.</span><small class="figure-copyright">Foto von <a class="link" href="https://unsplash.com/de/@ssergiomedinaa?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Sergio Medina</a></small></figcaption>

                </figure>

            </div>

        </div>

    </div>
    <div class="doc-section">

        <h2 class="doc-section-title">Grafik</h2>

        <div class="doc-variant-samples">

            <div data-media-overlay data-action="open" data-trigger-selector=".figure a" data-type="image">
                <figure class="figure" data-intrinsic-ratio="true" style="">

                    <a href="../../images/placeholder/flow-chart.svg" target="_blank">
                        <img class="figure-image" src="../../images/placeholder/flow-chart.svg" alt="Alternative Bildbeschreibung" />

                    </a>

                    <figcaption class="figure-caption"><span>Abbildung mit freiem Seitenverhältnis (nur für Grafiken)</span><small class="figure-copyright">Quelle: Unbekannt</small></figcaption>

                </figure>

            </div>

        </div>

    </div>

</div>

<!-- Default -->


<!-- Vue Component -->
<script type="text/x-template" id="mediaOverlay-overlay-template">

    <div class="mediaOverlay" :data-visible="isVisible == true">

        <nav class="mediaOverlay-nav">
            <button class="mediaOverlay-close" data-action="close"><span>{{{labels.close}}}</span></button>
        </nav>

        <div class="mediaOverlay-header">
            <div v-if="asset.description" class="mediaOverlay-description">
                <span v-html="asset.description.caption" class="mediaOverlay-caption"></span> <span v-html="asset.description.copyright" class="mediaOverlay-copyright"></span>
            </div>

            <div v-if="asset.cta.url" class="mediaOverlay-cta">
                <a :href="asset.cta.url" class="button" download=""><svg class="icon is-download-simple"><use xlink:href="/icons/icons-bold.svg#icon--download-simple"></use></svg><span class="button-label">Herunterladen</span></a>
            </div>
        </div>

        <div class="mediaOverlay-content" :data-type="asset.type">

            <!-- Image -->
            <figure v-if="asset.image && asset.image.src" class="mediaOverlay-figure">
                <img class="figure-image" :src="asset.image.src" :alt="asset.image.alt" :style="{ 'background-image': 'url(' + asset.image.lowres + ')' }" data-trigger="">
            </figure>

            <!-- Video -->
            <div v-if="asset.video && asset.video.src" class="mediaOverlay-figure">
                <figure class="videoPlayer">
                    <div class="videoPlayer-video">
                        <video :poster="asset.video.poster" class="video" controls>
                            <source :src="asset.video.src" :type="asset.video.type">
                        </video>
                    </div>
                </figure>
            </div>

            <!-- YouTube video -->
            <figure v-if="asset.video && asset.video.isYouTube" class="mediaOverlay-figure is-youtube">
                <iframe :src="'https://www.youtube-nocookie.com/embed/' + asset.video.id + '?rel=0'"  width="1280" height="720" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
            </figure>

            <!-- Audio -->
            <div v-if="asset.audio && asset.audio.src" class="mediaOverlay-figure">
                <figure class="audioPlayer">
                    <div v-if="asset.audio.poster" class="audioPlayer-poster" aria-hidden="true">
                        <img :src="asset.audio.poster" alt=""/>
                    </div>
                    <div class="audioPlayer-audio">
                        <audio :src="asset.audio.src" class="audio" controls></audio>
                    </div>
                </figure>
            </div>

        </div>

    </div>

</script>

<div v-cloak id="mediaOverlay">
    <overlay></overlay>
</div>

<!-- Blocked Video -->
<div id="mediaOverlay" data-v-app="" style="transition-duration: 150ms;">
    <div class="mediaOverlay" data-visible="true" style="--aspect-ratio: 1504/846;">
        <nav class="mediaOverlay-nav"><button class="mediaOverlay-close" data-action="close" data-active="true" data-trigger=""><span>Schließen</span></button></nav>
        <div class="mediaOverlay-header">
            <div class="mediaOverlay-description"><span class="mediaOverlay-caption">Ich bin der Titel des Mediums</span> <span class="mediaOverlay-copyright"></span></div>
        </div>
        <div class="mediaOverlay-content" data-type="video">
            <figure class="mediaOverlay-figure is-youtube">
                <iframe src="https://cloud.ccm19.de/x-content-blocked.html?apiKey=d25f730e279e287e431f83c2f4b78964c741fa1266190ca5&domain=664f6d5790e20920600adc62&gen=2&theme=664f6d5790e20920600adc71&lang=de_DE&v=1733243400&url=https%3A%2F%2Fwww.youtube-nocookie.com%2Fembed%2F2eRWscBHHAI%3Frel%3D0&embedding=674eb432b73797f4e20c9c97" width="1280" height="720" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
                <div class="ccm--consent-switch"><input id="ccm--consent-switch-e3ad1c8910caef19" type="checkbox"><label for="ccm--consent-switch-e3ad1c8910caef19">Inhalt für "YouTube Video" zulassen</label><a href="javascript:">(Details zum Anbieter)</a></div>
            </figure>
        </div>
    </div>
</div>

<!-- Demo Only -->
{{> '@mediaoverlay--vue-component'}}

<div style="min-height: 100vh;"><!-- Force displaying scrollbar -->

        {{#variants}}
    <div class="doc-section">

        {{#title}}
    <h2 class="doc-section-title">{{{.}}}</h2>
        {{/title}}

    <div class="doc-variant-samples">

            {{#unless mediagallery}}
        <div data-media-overlay data-action="open"{{#trigger-selector}} data-trigger-selector="{{.}}"{{/trigger-selector}}{{#type}} data-type="{{.}}"{{/type}}>
            {{#figure}}
                {{render '@figure' (contextData '@mediaoverlay' this) merge=true}}
            {{/figure}}
        </div>
            {{/unless}}

        {{#mediagallery}}
            {{render '@mediagallery' (contextData '@mediaoverlay' this) merge=true}}
        {{/mediagallery}}

    </div>

    </div>
        {{/variants}}

</div>
/* Default */
{
  "is-visible": false,
  "labels": {
    "close": "Schließen"
  },
  "description": {
    "caption": "Selfies fixie next level trust fund jean shorts photo booth raw denim butcher mixtape ethical mustache.",
    "copyright": "Foto von <a class=\"link\" href=\"https://unsplash.com/de/@ssergiomedinaa?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText\">Sergio Medina</a>"
  },
  "figure": {
    "src": "/images/placeholder/dummy-image.jpg",
    "alt": "Alternative Bildbeschreibung",
    "caption": "Selfies fixie next level trust fund jean shorts photo booth raw denim butcher mixtape ethical mustache.",
    "copyright": "Foto von <a class=\"link\" href=\"https://unsplash.com/de/@ssergiomedinaa?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText\">Sergio Medina</a>"
  },
  "cta": {
    "label": "Herunterladen",
    "is-download": "download",
    "icon": {
      "id": "download-simple",
      "weight": "bold"
    }
  }
}

/* Vue Component */
{
  "is-visible": false,
  "labels": {
    "close": "Schließen"
  },
  "description": {
    "caption": "Selfies fixie next level trust fund jean shorts photo booth raw denim butcher mixtape ethical mustache.",
    "copyright": "Foto von <a class=\"link\" href=\"https://unsplash.com/de/@ssergiomedinaa?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText\">Sergio Medina</a>"
  },
  "figure": {
    "src": "/images/placeholder/dummy-image.jpg",
    "alt": "Alternative Bildbeschreibung",
    "caption": "Selfies fixie next level trust fund jean shorts photo booth raw denim butcher mixtape ethical mustache.",
    "copyright": "Foto von <a class=\"link\" href=\"https://unsplash.com/de/@ssergiomedinaa?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText\">Sergio Medina</a>"
  },
  "cta": {
    "label": "Herunterladen",
    "is-download": "download",
    "icon": {
      "id": "download-simple",
      "weight": "bold"
    }
  }
}

/* Blocked Video */
{
  "is-visible": false,
  "labels": {
    "close": "Schließen"
  },
  "description": {
    "caption": "Selfies fixie next level trust fund jean shorts photo booth raw denim butcher mixtape ethical mustache.",
    "copyright": "Foto von <a class=\"link\" href=\"https://unsplash.com/de/@ssergiomedinaa?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText\">Sergio Medina</a>"
  },
  "figure": {
    "src": "/images/placeholder/dummy-image.jpg",
    "alt": "Alternative Bildbeschreibung",
    "caption": "Selfies fixie next level trust fund jean shorts photo booth raw denim butcher mixtape ethical mustache.",
    "copyright": "Foto von <a class=\"link\" href=\"https://unsplash.com/de/@ssergiomedinaa?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText\">Sergio Medina</a>"
  },
  "cta": {
    "label": "Herunterladen",
    "is-download": "download",
    "icon": {
      "id": "download-simple",
      "weight": "bold"
    }
  }
}

/* Demo Only */
{
  "is-visible": false,
  "labels": {
    "close": "Schließen"
  },
  "description": {
    "caption": "Selfies fixie next level trust fund jean shorts photo booth raw denim butcher mixtape ethical mustache.",
    "copyright": "Foto von <a class=\"link\" href=\"https://unsplash.com/de/@ssergiomedinaa?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText\">Sergio Medina</a>"
  },
  "figure": {
    "src": "/images/placeholder/dummy-image.jpg",
    "alt": "Alternative Bildbeschreibung",
    "caption": "Selfies fixie next level trust fund jean shorts photo booth raw denim butcher mixtape ethical mustache.",
    "copyright": "Foto von <a class=\"link\" href=\"https://unsplash.com/de/@ssergiomedinaa?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText\">Sergio Medina</a>"
  },
  "cta": {
    "label": "Herunterladen",
    "is-download": "download",
    "icon": {
      "id": "download-simple",
      "weight": "bold"
    }
  },
  "variants": [
    {
      "title": "Galerie mit Bildern",
      "mediagallery": {
        "title": null,
        "items": [
          {
            "type": "image",
            "caption": "Ich bin der Titel des Mediums",
            "copyright": "Foto von <a class=\"link\" href=\"https://unsplash.com/de/@ssergiomedinaa?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText\">Sergio Medina</a>",
            "preview": {
              "src": "/images/placeholder/dummy-image-640w.jpg",
              "alt": "Alternative Bildbeschreibung"
            },
            "link": {
              "url": "/images/placeholder/dummy-image-full-size.jpg",
              "download": true,
              "target": "_blank"
            },
            "zoom": {
              "src": "/images/placeholder/dummy-image.jpg"
            }
          },
          {
            "type": "image",
            "caption": "Overlay ohne Download",
            "copyright": "Foto von <a class=\"link\" href=\"https://unsplash.com/de/@ssergiomedinaa?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText\">Sergio Medina</a>",
            "preview": {
              "src": "/images/placeholder/dummy-image-640w.jpg",
              "alt": "Alternative Bildbeschreibung"
            },
            "link": {
              "url": "/images/placeholder/dummy-image-full-size.jpg",
              "download": false,
              "target": "_blank"
            },
            "zoom": {
              "src": "/images/placeholder/dummy-image.jpg"
            }
          },
          {
            "type": "image",
            "caption": "Ich bin der Titel des Mediums",
            "preview": {
              "src": "https://picsum.photos/id/18/480/720",
              "alt": "Alternative Bildbeschreibung"
            },
            "link": {
              "url": "https://picsum.photos/id/18/1120/1680",
              "download": true,
              "target": "_blank"
            }
          },
          {
            "type": "image",
            "caption": "Ich bin der Titel des Mediums",
            "preview": {
              "src": "https://picsum.photos/id/193/720/360",
              "alt": "Alternative Bildbeschreibung"
            },
            "link": {
              "url": "https://picsum.photos/id/193/1680/840",
              "download": true,
              "target": "_blank"
            }
          }
        ]
      }
    },
    {
      "title": "Galerie mit Video- und Audiodateien",
      "mediagallery": {
        "title": null,
        "items": [
          {
            "type": "video",
            "caption": "Ich bin der Titel des Mediums",
            "copyright": "Video von <a class=\"link\" href=\"https://pixabay.com/de/videos/gelb-fl%C3%BCssig-farbe-raum-27803/\">Pixabay</a>",
            "preview": {
              "src": "/videos/placeholder/dummy-video.jpg",
              "alt": "Alternative Beschreibung des Videos"
            },
            "link": {
              "url": "/videos/placeholder/dummy-video.mp4"
            }
          },
          {
            "type": "video",
            "link": {
              "url": "https://www.youtube-nocookie.com/watch?v=kg2fwlFsZss"
            },
            "caption": "Ich bin der Titel des Mediums",
            "preview": {
              "src": "https://img.youtube.com/vi/kg2fwlFsZss/maxresdefault.jpg",
              "alt": "Alternative Beschreibung des Videos"
            }
          },
          {
            "type": "audio",
            "caption": "Ich bin der Titel des Mediums",
            "copyright": "Audio von <a class=\"link\" href=\"https://pixabay.com/sound-effects/birds-chirping-ambiance-26052/\">Pixabay</a>",
            "preview": {
              "src": "/audios/placeholder/dummy-audio-poster.jpg",
              "alt": "Alternative Beschreibung des Tons"
            },
            "link": {
              "url": "/audios/placeholder/dummy-audio.mp3"
            }
          },
          {
            "type": "audio",
            "caption": "Audiodatei ohne Vorschau",
            "link": {
              "url": "/audios/placeholder/dummy-audio.mp3"
            }
          }
        ]
      }
    },
    {
      "title": "Video",
      "trigger-selector": ".figure a",
      "type": "video",
      "figure": {
        "src": "/videos/placeholder/dummy-video.jpg",
        "link": {
          "url": "/videos/placeholder/dummy-video.mp4",
          "target": "_blank"
        }
      }
    },
    {
      "title": "Youtube Video",
      "trigger-selector": ".figure a",
      "type": "video",
      "figure": {
        "src": "https://img.youtube.com/vi/kg2fwlFsZss/maxresdefault.jpg",
        "link": {
          "url": "https://www.youtube-nocookie.com/watch?v=kg2fwlFsZss",
          "target": "_blank"
        }
      }
    },
    {
      "title": "Grafik",
      "trigger-selector": ".figure a",
      "type": "image",
      "figure": {
        "intrinsic-ratio": true,
        "src": "/images/placeholder/flow-chart.svg",
        "caption": "Abbildung mit freiem Seitenverhältnis (nur für Grafiken)",
        "copyright": "Quelle: Unbekannt",
        "link": {
          "url": "/images/placeholder/flow-chart.svg",
          "target": "_blank"
        }
      }
    }
  ]
}

  • Content:
    export default (function (){
    
        const defaults = {
            selectors: {
                overlay: '#mediaOverlay',
                trigger: '.mediaOverlay [data-action], [data-media-overlay][data-action]',
                content: '.mediaOverlay-content',
                image: '[data-type="image"] .mediaOverlay-figure img',
            },
            types: [
                "image",
                "video",
                "audio",
                "iframe",
            ],
            durations: {
                visibility: 150,
            },
            minWidth: 640,
            showFocus: false,
        };
    
        function init(options) {
    
            options = options || {};
    
            const settings = Object.assign({}, defaults, options);
    
            if (typeof settings.minWidth === "number" && window.innerWidth < settings.minWidth) {
                return;
            }
    
            const overlay = document.querySelector(defaults.selectors.overlay);
    
            if (overlay) {
                new Overlay(overlay, options);
            }
    
        }
    
        const Overlay = function(appContainer, options) {
    
            this.settings = Object.assign({}, defaults, options);
    
            if (typeof this.settings.durations.visibility === "number") {
                appContainer.style.transitionDuration = this.settings.durations.visibility + "ms";
            }
    
            // Data prototype
    
            this._data = {
                isVisible: false,
                asset: {
                    image: {
                        src: null,
                        alt: null,
                        lowres: null,
                    },
                    video: {
                        src: null,
                        type: "video/mp4", // FIXME: Should be customisable
                        poster: null,
                        id: null,
                        isYouTube: false,
                    },
                    audio: {
                        src: null,
                        poster: null,
                        id: null,
                    },
                    description: {
                        caption: null,
                        copyright: null,
                    },
                    cta: {
                        link: null,
                    }
                },
            };
    
            // Vue component
    
            this.data = Vue.reactive(Object.assign({}, this._data));
            const data = this.data;
    
            this.vue = Vue.createApp({
                data() {
                    return data;
                },
                methods: {
                },
            }).component("overlay", {
                template: "#mediaOverlay-overlay-template",
                data() {
                    return data;
                },
            }).mount(appContainer);
    
            this.container = this.vue.$el;
    
            // Actions
    
            const actions = {
                open: (data) => this.open(data),
                close: () => this.close(),
            };
    
            // Init triggers
    
            const triggers = document.querySelectorAll(defaults.selectors.trigger);
    
            this.currentTrigger = null;
    
            triggers.forEach((element) => {
    
                if (typeof element.dataset.action !== "string" || typeof actions[element.dataset.action] !== "function") {
                    console.warn(`mediaOverlay: Action "${element.dataset.action}" not defined!`);
                    return;
                }
    
                const action = element.dataset.action;
    
                element.setAttribute("data-active", "true");
    
                // Collect Data
    
                let assetData = {};
    
                if (action === "open") {
                    assetData = this.getAssetData(element);
                }
    
                // Trigger
    
                let trigger = element;
    
                if (typeof element.dataset.triggerSelector === "string" && element.dataset.triggerSelector !== "") {
    
                    const selector = element.dataset.triggerSelector;
                    let selectedElement = element.querySelector(selector);
    
                    if (selectedElement) {
                        trigger = selectedElement;
                    } else {
                        console.warn(`mediaOverlay: Trigger "${selector}" not found.`);
                    }
    
                }
    
                trigger.setAttribute("data-trigger", "");
    
                trigger.addEventListener("click", (event) => {
                    event.preventDefault();
                    if (action === "open") {
                        this.currentTrigger = trigger;
                    }
                    actions[action](assetData);
                });
    
            });
    
            // Add blocker
    
            this.blocker = document.createElement("div");
    
            this.blocker.classList.add("mediaOverlay-blocker");
            this.blocker.style.display = "none";
    
            const contentContainer = this.container.querySelector(this.settings.selectors.content);
    
            if (! contentContainer) {
                console.warn(`mediaOverlay: Container "${this.settings.selectors.content}" for blocker not found.`);
            } else {
                contentContainer.appendChild(this.blocker);
            }
    
            this.siblings = appContainer.parentNode.querySelectorAll(`:scope > *:not(${defaults.selectors.overlay})`);
    
            // Add keyboard controls
    
            document.addEventListener('keydown', (e) => {
    
                if (! this.data.isVisible) {
                    return true;
                }
    
                let preventDefault = false;
    
                if ([27, 32].indexOf(e.keyCode) !== -1) {
                    preventDefault = true;
                    this.close();
                }
    
                if (preventDefault) {
                    e.preventDefault();
                }
    
            });
    
        }
    
        Overlay.prototype.getAssetData = function(container) {
    
            const data = deepClone(this._data.asset);
    
            data.type = "image";
    
            if (typeof container.dataset.type === "string" && container.dataset.type !== "" && this.settings.types.includes(container.dataset.type)) {
                data.type = container.dataset.type;
            }
    
            if (container.querySelector("figure")) {
    
                const source = container.querySelector("figure");
    
                // Image or video URL
    
                let previewUrl = "",
                    mediaUrl = "",
                    downloadUrl = "";
    
                if (source.querySelector("img[src]")) {
    
                    const image = source.querySelector("img[src]");
    
                    previewUrl = image.src;
    
                    if (typeof image.dataset.zoom === "string" && image.dataset.zoom !== "") {
                        mediaUrl = image.dataset.zoom;
                    }
    
                }
    
                if (source.querySelector("a[href]")) {
    
                    if (mediaUrl === "") {
                        mediaUrl = source.querySelector("a[href]").href;
                    }
    
                    if (source.querySelector("a[href]").hasAttribute("download")) {
                        downloadUrl = source.querySelector("a[href]").href;
                    }
    
                }
    
                if (mediaUrl === "" && previewUrl) {
                    mediaUrl = previewUrl;
                }
    
                if (mediaUrl === "") {
                    console.warn("mediaOverlay: No source found!");
                    return data;
                }
    
                if (data.type === "video") {
    
                    data.video.src = mediaUrl;
                    data.video.poster = previewUrl;
    
                    data.video.id = this.getVideoId(mediaUrl);
    
                    data.video.isYouTube = typeof data.video.id === "string";
    
                    if (data.video.isYouTube) {
                        data.video.src = null;
                    }
    
                } else if (data.type === "audio") {
    
                    data.audio.src = mediaUrl;
                    data.audio.poster = previewUrl;
    
                } else if (data.type === "iframe") {
    
                } else {
    
                    data.image.src = mediaUrl;
                    data.image.lowres = previewUrl;
    
                }
    
                // Image alt
    
                if (source.querySelector("img[alt]")) {
    
                    data.image.alt = source.querySelector("img[alt]").alt;
    
                }
    
                // Description
    
                if (source.querySelector("figcaption")) {
    
                    const caption = source.querySelector("figcaption");
    
                    if (caption.querySelector(":scope > span")) {
                        data.description.caption = caption.querySelector(":scope > span").innerHTML;
                    }
    
                    if (caption.querySelector('[class*="copyright"')) {
                        data.description.copyright = caption.querySelector('[class*="copyright"').innerHTML;
                    }
    
                }
    
                // CTA
    
                if (downloadUrl !== "") {
                    data.cta.url = downloadUrl;
                }
    
            }
    
            return data;
    
        }
    
        Overlay.prototype.getVideoId= function(url) {
    
            let regExp = /^.*((youtu.be\/)|(v\/)|(\/u\/\w\/)|(embed\/)|(watch\?))\??v?=?([^#&?]*).*/,
                matches = url.match(regExp);
    
            if (! matches || ! matches[7].length === 11) {
                return null;
            }
    
            return matches[7];
    
        }
    
        Overlay.prototype.open = function(asset) {
    
            this.data.asset = asset;
    
            this.vue.$nextTick(() => {
    
                const image = this.container.querySelector(this.settings.selectors.image);
    
                if (image) {
    
                    image.addEventListener('load', (e) => {
                        this.showBlocker(e.target);
                    });
    
                }
    
                const media = this.container.querySelector("iframe, .audioPlayer, .videoPlayer");
    
                if (media) {
                    this.setMediaSize(media);
                }
    
                const closeButton = this.container.querySelector('[data-action="close"]');
    
                if (closeButton) {
                    closeButton.focus({ focusVisible: this.settings.showFocus });
                }
    
                this.inertSiblings(true);
    
            });
    
            this.toggle(true);
    
        }
    
        Overlay.prototype.close = function() {
    
            this.data.asset = this._data.asset;
            this.container.style.removeProperty("--aspect-ratio");
    
            this.inertSiblings(false);
    
            if (this.currentTrigger) {
                this.currentTrigger.focus({ focusVisible: this.settings.showFocus });
                this.currentTrigger = null;
            }
    
            this.showBlocker();
    
            this.toggle(false);
    
        }
    
        Overlay.prototype.toggle = function(isVisible) {
    
            if (typeof isVisible !== "boolean") {
                isVisible = ! this.data.isVisible;
            }
    
            this.data.isVisible = isVisible;
            document.querySelector("html").dataset.mediaOverlayVisible = isVisible;
    
        }
    
        Overlay.prototype.updateVue = function() {
    
            if (typeof this.vue === "object") {
                this.vue.$forceUpdate();
            }
    
        }
    
        Overlay.prototype.setMediaSize = function(element) {
    
            this.container.style.setProperty("--aspect-ratio", element.clientWidth + "/" + element.clientHeight);
    
            const contentContainer = this.container.querySelector(this.settings.selectors.content);
    
            if (! contentContainer) {
                return;
            }
    
            const paddingLeft = getPadding(contentContainer, "left"),
                  paddingRight = getPadding(contentContainer, "right"),
                  maxWidth = contentContainer.clientWidth - (paddingLeft + paddingRight);
    
            if (element.offsetWidth > maxWidth) {
                element.style.width = maxWidth + "px";
                element.style.height = "auto";
            }
    
        }
    
        Overlay.prototype.showBlocker = function(image) {
    
            if (typeof image !== "object") {
                this.blocker.style.display = "none";
                return;
            }
    
            this.blocker.style.display = "block";
    
            const dimension = getRenderedSize(image);
    
            this.blocker.style.width = dimension.width + "px";
            this.blocker.style.height = dimension.height + "px";
    
        }
    
        Overlay.prototype.inertSiblings = function(inert) {
    
            this.siblings.forEach(sibling => {
    
                if (inert) {
                    sibling.setAttribute("inert", "");
                } else {
                    sibling.removeAttribute("inert");
                }
    
            });
    
        }
    
        function getRenderedSize(image, objectFit){
    
            if (typeof objectFit !== "string") {
                objectFit = "contain";
            }
    
            const imageWidth = image.naturalWidth,
                  imageHeight = image.naturalHeight,
                  containerWidth = image.width,
                  containerHeight = image.height;
    
            const imageRatio = imageWidth / imageHeight,
                  containerRatio = containerWidth / containerHeight;
    
            let width = containerWidth,
                height = containerHeight;
    
            if (objectFit == "contain") {
    
                if (imageRatio > containerRatio) {
                    height = containerWidth / imageRatio;
                } else {
                    width = containerHeight * imageRatio;
                }
    
            } else if (objectFit == "cover") {
    
                if (imageRatio < containerRatio) {
                    height = containerWidth / imageRatio;
                } else {
                    width = containerHeight * imageRatio;
                }
    
            }
    
            return {
                width: width,
                height: height,
            };
    
        }
    
        const getPadding = function(element, side) {
    
            let padding = 0;
    
            if (typeof element !== "object" || typeof side !== "string" || ! ["top", "bottom", "left", "right", "inline", "block"].includes(side)) {
                return padding;
            }
    
            padding = window.getComputedStyle(element).getPropertyValue("padding-" + side);
    
            return parseInt(padding);
    
        }
    
        const deepClone = function(object) {
            return JSON.parse(JSON.stringify(object));
        }
    
        return {
            init: init
        }
    
    })();
    
  • URL: /components/raw/mediaoverlay/_mediaOverlay.script.js
  • Filesystem Path: components/04-modules/mediaOverlay/_mediaOverlay.script.js
  • Size: 13.6 KB
  • Content:
    $mediaOverlay_background: rgba($_GRAY-900, .93) !default;
    $mediaOverlay_header_background: $_gray-900 !default;
    
    $mediaOverlay-close_stroke-width: 2 !default;
    
    $mediaOverlay_icons: (
        close: '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" stroke="{{color}}" stroke-width="#{$mediaOverlay-close_stroke-width}" stroke-linecap="round" stroke-linejoin="round"><path d="M18.75 5.25L5.25 18.75"/><path d="M18.75 18.75L5.25 5.25"/></svg>',
        zoom-in: '<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg" stroke="{{color}}" stroke-width="#{$mediaOverlay-close_stroke-width}" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6H26V12"/><path d="M19 13L26 6"/><path d="M12 26H6V20"/><path d="M13 19L6 26"/><path d="M26 20V26H20"/><path d="M19 19L26 26"/><path d="M6 12V6H12"/><path d="M13 13L6 6"/></svg>',
    ) !default;
    
    $mediaOverlay_zoom-in_styles: (
        width: 48px,
        height: 48px,
        background: $_black center center no-repeat,
        background-image: svg-url(map.get($mediaOverlay_icons, zoom-in), $white),
        background-size: 32px,
        color: $white,
        border-radius: 3px,
        transition-duration: $_transition-duration--in,
        transition-timing-function: easing(),
        transition-property: (background-size, transform),
    ) !default;
    
    $mediaOverlay_zoom-in_states: (
        default: $mediaOverlay_zoom-in_styles,
        hover: (
            background-size: 40px,
            transform: scale(1.1),
            transition-timing-function: easing(back, in),
        ),
        focus: map.merge( $_focus_styles,
            (
                opacity: 1,
            )
        ),
    ) !default;
    
    @import "_mediaOverlay.settings";
    @import "_mediaOverlay.styles";
    
    %mediaOverlay {
        backdrop-filter: blur(5px);
    
        a.button {
            @extend %button--small;
            @extend %button--alt--secondary;
            @include stack-spacing(0);
        }
    
        .ccm--consent-switch {
            pointer-events: all;
            user-select: none;
    
            display: flex;
            align-items: center;
            flex-wrap: wrap;
            gap: .5ch;
    
            height: $mediaOverlay_padding;
    
            position: absolute;
            bottom: 0;
    
            @include text-size(smallest);
            color: $_minor-color;
    
            a {
                color: inherit;
    
                &:hover {
                    text-decoration-color: $_action-color--hover;
                }
    
            }
    
        }
    
    }
    
  • URL: /components/raw/mediaoverlay/_mediaOverlay.scss
  • Filesystem Path: components/04-modules/mediaOverlay/_mediaOverlay.scss
  • Size: 2.4 KB
  • Content:
    $mediaOverlay_padding: var(--bp-large) !default;
    $mediaOverlay_max-width: $_page_max-width !default;
    
    $mediaOverlay_background: black !default;
    $mediaOverlay-header_background: rgba(white, .2) !default;
    
    $mediaOverlay-close_stroke-width: 2 !default;
    
    $mediaOverlay_icons: (
        close: '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" stroke="{{color}}" stroke-width="#{$mediaOverlay-close_stroke-width}" stroke-linecap="round" stroke-linejoin="round"><path d="M18.75 5.25L5.25 18.75"/><path d="M18.75 18.75L5.25 5.25"/></svg>',
        zoom-in: '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" stroke="{{color}}" stroke-width="#{$mediaOverlay-close_stroke-width}" stroke-linecap="round" stroke-linejoin="round"><path d="M15 4.5H19.5V9"/><path d="M14.25 9.75L19.5 4.5"/><path d="M9 19.5H4.5V15"/><path d="M9.75 14.25L4.5 19.5"/><path d="M19.5 15V19.5H15"/><path d="M14.25 14.25L19.5 19.5"/><path d="M4.5 9V4.5H9"/><path d="M9.75 9.75L4.5 4.5"/></svg>',
    ) !default;
    
    $mediaOverlay_zoom-in_styles: (
        width: 32px,
        height: 32px,
        background: $_black center center no-repeat,
        background-image: svg-url(map.get($mediaOverlay_icons, zoom-in), $white),
        color: $white,
        opacity: .66,
        transition-duration: $_transition-duration,
        transition-property: opacity,
    ) !default;
    
    $mediaOverlay_zoom-in_states: (
        default: $mediaOverlay_zoom-in_styles,
        hover: (
            opacity: 1,
        ),
        focus: map.merge( $_focus_styles,
            (
                opacity: 1,
            )
        ),
    ) !default;
    
    $mediaOverlay_close_styles: (
        width: 32px,
        height: 32px,
        background: transparent center center no-repeat,
        background-image: svg-url(map.get($mediaOverlay_icons, close), $white),
        color: $white,
        border-radius: 100vmax,
        transition-duration: $_transition-duration,
        transition-property: (background-color, color),
    ) !default;
    
    $mediaOverlay_close_states: (
        default: $mediaOverlay_close_styles,
        hover: (
            background-color: $_action-background-color--hover,
            color: $_action-foreground-color--hover,
            transition-duration: $_transition-duration--in,
        ),
        focus: $_focus_styles,
        active: (
            background-color: $_action-background-color--active,
            color: $_action-foreground-color--active,
            transition-duration: $_transition-duration--in,
        ),
    ) !default;
    
  • URL: /components/raw/mediaoverlay/_mediaOverlay.settings.scss
  • Filesystem Path: components/04-modules/mediaOverlay/_mediaOverlay.settings.scss
  • Size: 2.4 KB
  • Content:
    %mediaOverlay {
        position: fixed;
        top: 0;
        left: 0;
        width: 100vw;
        height: 100vh;
        @include z-index(mediaOverlay);
    
        display: grid;
        grid-template-rows: 1fr max-content;
        grid-template-areas:
            "content"
            "header";
        align-items: stretch;
    
        --aspect-ratio: 16 / 9;
    
        @include apply-theme(dark);
    
        background: $mediaOverlay_background;
    
        overflow: hidden;
    
        opacity: 0;
        visibility: hidden;
        pointer-events: none;
    
        transition: opacity 150ms, pointer-events 0s, visibility 0s;
    
        &[data-visible="true"] {
            opacity: 1;
            visibility: visible;
            pointer-events: all;
        }
    
        &-nav {
            position: absolute;
            top: 0;
            left: 0;
    
            z-index: -1;
    
            width: 100%;
            height: 100%;
        }
    
        &-close {
            display: block;
            width: 100%;
            height: 100%;
    
            position: absolute;
            top: 0;
            left: 0;
            z-index: -1;
    
            cursor: default !important;
    
            outline: none;
    
            &:not([disabled]):not([aria-disabled="true"]):focus-visible > span {
                @include state-styles($mediaOverlay_close_states, focus);
            }
    
            > span {
                cursor: pointer;
    
                position: absolute;
                top: calc(.5 * #{$mediaOverlay_padding});
                right: calc(.5 * #{$mediaOverlay_padding});
                transform: translate(50%, -50%);
    
                display: block;
    
                text-indent: 120%;
                white-space: nowrap;
                overflow: hidden;
    
                @include styles($mediaOverlay_close_styles);
                @include action-states($mediaOverlay_close_states);
    
                $mask-image: get-style($mediaOverlay_close_styles, background-image);
    
                @if $mask-image {
    
                    @supports (mask-image: url()) {
                        background-image: none;
    
                        &::after {
                            content: "";
    
                            position: absolute;
                            inset: 0;
    
                            background: currentcolor;
    
                            mask-image: $mask-image;
                            mask-repeat: no-repeat;
                            mask-position: center center;
                        }
    
                    }
    
                }
    
            }
    
        }
    
        &-header {
            grid-area: header;
            padding: var(--bp-small) var(--bp-large);
            background: $mediaOverlay_header_background;
    
            display: flex;
            flex-wrap: wrap;
            align-items: center;
            column-gap: var(--gg);
            row-gap: var(--sp-large);
    
            position: relative;
            z-index: 1;
        }
    
        &-description {
            flex: 1;
            min-width: 320px;
        }
    
        &-description:not(:has(~ .mediaOverlay-cta))  {
            text-align: center;
        }
    
        &-caption {
            padding-right: 1ch;
        }
    
        &-copyright {
            @extend %figure-copyright;
        }
    
        &-cta {
    
            .button {
                @include stack-spacing(0);
            }
    
        }
    
        &-content {
            grid-area: content;
    
            padding: $mediaOverlay_padding;
            max-width: $mediaOverlay_max-width;
            margin-left: auto;
            margin-right: auto;
    
            display: flex;
            justify-content: center;
    
            overflow: hidden;
            pointer-events: none;
    
            position: relative;
    
            &[data-type="audio"],
            &[data-type="video"],
            &[data-type="iframe"] {
                align-items: center;
                width: 100%;
                height: 100%;
            }
    
            > * {
                @include stack-spacing(0);
                display: flex;
                justify-content: center;
            }
    
        }
    
        &-content[data-type="audio"] &-figure,
        &-content[data-type="video"] &-figure,
        &-content[data-type="iframe"] &-figure {
            width: auto;
            height: 100%;
    
            align-items: center;
        }
    
        &-content[data-type="audio"] &-figure,
        &-content[data-type="video"] &-figure {
            aspect-ratio: var(--aspect-ratio);
        }
    
        &-figure {
            width: 100%;
    
            .figure-caption {
                display: none;
            }
    
            .figure-image {
                @include stack-spacing(0);
    
                width: auto;
                max-width: 100%;
                object-fit: contain;
                object-position: center;
    
                &[style*="background-image"] {
                    background-size: 0px;
                    position: relative;
    
                    &::after {
                        content: "";
    
                        position: absolute;
                        inset: 0;
    
                        background-image: inherit;
                        background-size: contain;
    
                        filter: blur(3px);
                    }
    
                }
    
            }
    
            .audioPlayer,
            .videoPlayer {
                @include stack-spacing(0);
            }
    
            iframe {
                width: auto;
                height: 100%;
                aspect-ratio: var(--aspect-ratio, 16 / 9);
            }
    
            .videoPlayer {
                width: 100%;
            }
    
            .audioPlayer {
                width: 100%;
    
                &-audio:only-child {
                    margin: auto;
                    max-width: min(100%, 640px);
                }
    
            }
    
            audio,
            iframe,
            video {
                @include stack-spacing(0);
                pointer-events: all;
            }
    
        }
    
        &-content[data-type="audio"] &-figure {
            pointer-events: all;
        }
    
        &-content[data-type="iframe"] &-figure {
            width: 100%;
            max-height: 100%;
    
            overflow-y: auto;
            pointer-events: all;
    
            iframe {
                max-width: 100%;
            }
    
            &.is-youtube {
                //FIXME: Height of video can be taller than parent container
                //       ("object-fit" does not work with iframes).
    
                width: 100%;
                padding-bottom: 56.25%;
                overflow-y: hidden;
    
                position: relative;
    
                iframe {
                    position: absolute;
                    display: block;
    
                    height: 100%;
                    width: 100%;
    
                    pointer-events: all;
                }
    
            }
    
        }
    
        // Blocker for images
    
        &-blocker {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            z-index: 100;
    
            display: none;
            width: 100%;
            height: 100%;
    
            pointer-events: all;
        }
    
    }
    
    //** Actions **//
    
    %mediaOverlay_zoom-in {
        pointer-events: all !important;
        cursor: zoom-in;
    
        position: relative;
        z-index: 2;
    
        &:focus {
            outline: none;
        }
    
        @include action-states($mediaOverlay_zoom-in_states, $descendant: "::after");
    
        &::after {
            content: "";
            display: block;
    
            position: absolute;
            right: var(--bp-small);
            bottom: var(--bp-small);
    
            z-index: 3;
    
            @include styles($mediaOverlay_zoom-in_styles);
        }
    
    }
    
    *[data-media-overlay][data-action="open"][data-active="true"] {
    
        *[data-trigger] {
            @extend %mediaOverlay_zoom-in;
        }
    
        .mediaGallery-preview img {
            transform: none !important;
        }
    
    }
    
    .mediaOverlay {
        @extend %mediaOverlay;
    
        &-nav {
            @extend %mediaOverlay-nav;
        }
    
        &-close {
            @extend %mediaOverlay-close;
        }
    
        &-header {
            @extend %mediaOverlay-header;
        }
    
        &-content {
            @extend %mediaOverlay-content;
        }
    
        &-figure {
            @extend %mediaOverlay-figure;
        }
    
        &-description {
            @extend %mediaOverlay-description;
        }
    
        &-caption {
            @extend %mediaOverlay-caption;
        }
    
        &-copyright {
            @extend %mediaOverlay-copyright;
        }
    
        &-cta {
            @extend %mediaOverlay-cta;
        }
    
        &-blocker {
            @extend %mediaOverlay-blocker;
        }
    
    }
    
    html[data-media-overlay-visible="true"] {
        overflow: hidden;
    
        .grid-page {
            overflow: hidden;
        }
    
        @include only-on-desktop(){
            padding-right: var(--scrollbar-width) !important;
    
            .mainHeader,
            .mainNav {
                padding-right: var(--scrollbar-width) !important;
            }
    
        }
    
    }
    
  • URL: /components/raw/mediaoverlay/_mediaOverlay.styles.scss
  • Filesystem Path: components/04-modules/mediaOverlay/_mediaOverlay.styles.scss
  • Size: 8.1 KB