<figure id="media-16556-29452" class="media" role="figure" aria-labelledby="media-16556-29452-caption">
    <div class="media__figure">
        <div class="media__image">
            <picture class="image" style="background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAIAAAACDbGyAAAABGdBTUEAALGPC/xhBQAAADhlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAAqACAAQAAAABAAAABaADAAQAAAABAAAABQAAAABcYj7LAAAAFUlEQVQIHWP8V8PJgASYkNggJql8AHi/AY1z9PnwAAAAAElFTkSuQmCC)">
                <source srcset="https://bildermangel.de/1380x776/fe7c09/130f26.webp?text=+++M:+690x388@2x+++ 2x, https://bildermangel.de/690x388/fe7c09/130f26.webp?text=+++M:+690x388@1x+++ 1x" media="(min-width: 512px) and (max-width: 767px)">
                <source srcset="https://bildermangel.de/1760x990/fe7c09/130f26.webp?text=+++L:+880x495@2x+++ 2x, https://bildermangel.de/880x495/fe7c09/130f26.webp?text=+++L:+880x495@1x+++ 1x" media="(min-width: 768px) and (max-width: 1023px)">
                <source srcset="https://bildermangel.de/2048x1152/fe7c09/130f26.webp?text=+++XL:+1024x576@2x+++ 2x, https://bildermangel.de/1024x576/fe7c09/130f26.webp?text=+++XL:+1024x576@1x+++ 1x" media="(min-width: 1024px)">
                <img class="image__img" src="https://bildermangel.de/470x264/fe7c09/130f26.webp?text=+++S:+470x264@1x+++" srcset="https://bildermangel.de/940x528/fe7c09/130f26.webp?text=+++S:+470x264@2x+++ 2x" width="470" height="264" alt="Das ist ein Platzhalter-Bild" loading="lazy" />
            </picture>
        </div>

        <div class="media__button">

            <a class="button u-overlay-link" href="https://www.flickr.com/" rel="noopener noreferrer" target="_blank">
                <span class="button__icon">
                    <svg class="icon icon--arrow-up-right-from-square" viewBox="0 0 200 200" aria-hidden="true">
                        <use xlink:href="/assets/icons/icons.dcaca1c147.svg#arrow-up-right-from-square"></use>
                    </svg> </span>
                <span class="button__text u-underline">More images on Flickr</span>
            </a>
        </div>
    </div>

    <figcaption class="media__caption" id="media-16556-29452-caption">
        <div class="media__text">This is the caption <a class="link" data-link-type="external" href="https://example.com" rel="noopener noreferrer" target="_blank"><span class="link__icon"><svg class="icon icon--arrow-up-right-from-square" viewBox="0 0 200 200" aria-hidden="true">
                        <use xlink:href="/assets/icons/icons.dcaca1c147.svg#arrow-up-right-from-square"></use>
                    </svg>&#65279;</span><span class="link__text u-underline">with a link</span></a></div>

        <div class="media__copyright">
            <div class="copyright">
                <button class="copyright__button u-overlay-link" type="button" title="Image attribution" aria-pressed="false">
                    <svg class="icon icon--copyright" viewBox="0 0 200 200" aria-hidden="true">
                        <use xlink:href="/assets/icons/icons.dcaca1c147.svg#copyright"></use>
                    </svg> </button>

                <div class="copyright__floating" tabindex="0" role="floating" hidden data-floating-placements="bottom,top,left,right">Source: example.com</div>
            </div>
        </div>
    </figcaption>

</figure>
{% set id = id ?? html_id('media') %}
{% set caption = caption ?? image.caption ?? false %}
{% set copyright = copyright ?? image.copyright ?? false %}
{% set captionId = 'caption' | namespaceInputId(id) -%}

<figure {{ html_attributes({
  id: id,
  class: 'media',
  role: 'figure',
  'aria-labelledby': caption or copyright ? captionId,
}, attrs ?? {}) }}>
  <div class="media__figure">
    {% if image|default %}
      <div class="media__image">
        {% include '@image' with image only %}
      </div>

      {% if lightbox|default %}
        <div class="media__button">
          {% if lightboxText|default %}
            {% include '@button' with {
              overlay: true,
              text: lightboxText,
              icon: 'magnifying-glass-plus',
              attrs: {
                'data-media-lightbox': 'lightbox' | namespaceInputId(id),
              },
            } only %}
          {% else %}
            {% include '@button' with {
              overlay: true,
              title: 'Enlarge image' | t('site'),
              icon: 'magnifying-glass-plus',
              attrs: {
                'data-media-lightbox': 'lightbox' | namespaceInputId(id),
              },
            } only %}
          {% endif %}
        </div>
      {% elseif link|default %}
        <div class="media__button">
          {% include '@button' with link | merge({
            overlay: true,
          }) only %}
        </div>
      {% endif %}
    {% elseif video|default %}
      <div class="media__video">
        {% include '@video' with video only %}
      </div>
    {% endif %}
  </div>

  {% if caption or copyright %}
    <figcaption class="media__caption" id="{{ captionId }}">
      {% if caption %}
        <div class="media__text">
          {{- caption | componentize(inline_only=true) -}}
        </div>
      {% endif %}

      {% if copyright %}
        <div class="media__copyright">
          {% include '@copyright' with {
            text: copyright,
            overlay: true,
          } only %}
        </div>
      {% endif %}
    </figcaption>
  {% endif %}

  {% if image|default and lightbox|default %}
    <template id="{{ 'lightbox' | namespaceInputId(id) }}">
      <div class="media__lightbox" aria-hidden="true">
        <div class="media__lightbox-container">
          <div class="media__lightbox-image">
            {% include '@image' with lightbox only %}
          </div>

          <div class="media__lightbox-close">
            {% include '@button' with {
              icon: 'xmark',
              title: 'Close' | t('site'),
              attrs: {
                'data-media-lightbox-action': 'close',
              },
            } only %}
          </div>
        </div>
      </div>
    </template>
  {% endif %}
</figure>
{
  "caption": "This is the caption <a href=\"https://example.com\">with a link</a>",
  "copyright": "Source: example.com",
  "image": {
    "src": "https://bildermangel.de/470x264/fe7c09/130f26.webp?text=+++S:+470x264@1x+++",
    "width": 470,
    "height": 264,
    "alt": "Das ist ein Platzhalter-Bild",
    "src2x": "https://bildermangel.de/940x528/fe7c09/130f26.webp?text=+++S:+470x264@2x+++",
    "placeholder": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAIAAAACDbGyAAAABGdBTUEAALGPC/xhBQAAADhlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAAqACAAQAAAABAAAABaADAAQAAAABAAAABQAAAABcYj7LAAAAFUlEQVQIHWP8V8PJgASYkNggJql8AHi/AY1z9PnwAAAAAElFTkSuQmCC",
    "sources": [
      {
        "srcset": "https://bildermangel.de/690x388/fe7c09/130f26.webp?text=+++M:+690x388@1x+++",
        "srcset2x": "https://bildermangel.de/1380x776/fe7c09/130f26.webp?text=+++M:+690x388@2x+++",
        "media": "(min-width: 512px) and (max-width: 767px)"
      },
      {
        "srcset": "https://bildermangel.de/880x495/fe7c09/130f26.webp?text=+++L:+880x495@1x+++",
        "srcset2x": "https://bildermangel.de/1760x990/fe7c09/130f26.webp?text=+++L:+880x495@2x+++",
        "media": "(min-width: 768px) and (max-width: 1023px)"
      },
      {
        "srcset": "https://bildermangel.de/1024x576/fe7c09/130f26.webp?text=+++XL:+1024x576@1x+++",
        "srcset2x": "https://bildermangel.de/2048x1152/fe7c09/130f26.webp?text=+++XL:+1024x576@2x+++",
        "media": "(min-width: 1024px)"
      }
    ]
  },
  "link": {
    "text": "More images on Flickr",
    "link": "https://www.flickr.com/"
  }
}
  • Content:
    @use 'layers';
    
    .media {
      --_media-figure-inset-inline: 1.6rem;
      --_media-figure-inset-block: 1.6rem;
      --_media-copyright-size: 2.4rem;
    
      display: block;
      position: relative;
    }
    
    .media__figure {
      isolation: isolate;
      overflow: clip;
      position: relative;
      z-index: 1;
    }
    
    .media__image {
      border-radius: var(--border-radius-medium);
      overflow: clip;
      position: relative;
      z-index: 1;
    }
    
    .media:has(.media__copyright) :is(.plyr__controls) {
      padding-inline-end: calc(var(--_media-figure-inset-inline) * 2 + var(--_media-copyright-size) + 0.8rem);
    }
    
    .media__button {
      --overlay-link-inset: -100vw;
    
      display: flex;
      inset-block-end: 0;
      inset-inline-start: 0;
      padding-block: var(--_media-figure-inset-block);
      padding-inline: var(--_media-figure-inset-inline);
      position: absolute;
      z-index: 3;
    }
    
    .media__caption {
      position: relative;
      text-align: center;
      z-index: 2;
    }
    
    .media__text {
      margin-inline: auto;
      max-inline-size: 75%;
      min-inline-size: 50rem;
    }
    
    .media__copyright {
      --copyright-size: var(--_media-copyright-size);
      --overlay-link-inset: calc(var(--_media-figure-inset-block) * -1) calc(var(--_media-figure-inset-inline) * -1);
    
      inset-block-start: 0;
      inset-inline-end: 0;
      line-height: 0;
      padding-block: var(--_media-figure-inset-block);
      padding-inline: var(--_media-figure-inset-inline);
      position: absolute;
      translate: 0 -100%;
    }
    
    .media__text {
      color: var(--media-caption-color, var(--secondary-text-color));
      font-size: var(--media-caption-font-size, var(--font-size-caption));
      line-height: var(--media-caption-line-height, var(--line-height-regular));
      padding-block-start: var(--media-caption-gap, 1.2rem);
      padding-inline: var(--media-caption-padding-inline, 0);
    }
    
    .media__lightbox {
      --icon-button-size: 4rem;
      --_media-lightbox-padding: clamp(2rem, 10vw, 4rem);
    
      animation-duration: var(--duration-fast);
      animation-name: opacity;
      backdrop-filter: blur(10px);
      background-color: var(--media-lightbox-background-color, rgba(0, 0, 0, 0.8));
      color: var(--media-lightbox-color, var(--color-white));
      display: flex;
      flex-direction: column;
      inset: 0;
      overflow: hidden;
      overscroll-behavior: contain;
      padding-block-end: var(--_media-lightbox-padding);
      padding-block-start: calc(var(--_media-lightbox-padding) + 2rem + var(--icon-button-size));
      padding-inline: var(--_media-lightbox-padding);
      position: fixed;
      z-index: #{layers.position('overlay')};
    
      &:is([aria-hidden='true']) {
        display: none;
      }
    }
    
    .media__lightbox-container {
      align-items: center;
      block-size: 100%;
      display: flex;
      flex-direction: column;
      flex-grow: 1;
      inline-size: 100%;
      justify-content: center;
    }
    
    .media__lightbox-image {
      box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
      inline-size: 100%;
      position: relative;
    }
    
    .media__lightbox-close {
      inset-block-start: var(--_media-lightbox-padding);
      inset-inline-end: var(--_media-lightbox-padding);
      line-height: 0;
      pointer-events: all;
      position: absolute;
    }
    
  • URL: /components/raw/media/media.scss
  • Filesystem Path: src/components/3-molecules/media/media.scss
  • Size: 3 KB
  • Content:
    import { on } from 'delegated-events';
    import A11yDialog from 'a11y-dialog';
    import abort from '../../../javascripts/utils/abort';
    import fitImageInsideContainer from '../../../javascripts/utils/fitImageInsideContainer';
    
    on('click', '[data-media-lightbox]', (event) => {
      const { currentTarget: $trigger } = event;
      const { mediaLightbox: templateId } = $trigger.dataset;
    
      event.preventDefault();
    
      if (!templateId) {
        return;
      }
    
      const $media = $trigger.closest<HTMLElement>('.media') ?? abort();
      const $template = document.querySelector<HTMLTemplateElement>(`#${templateId}`) ?? abort();
      const $fragment = $template.content.cloneNode(true) as DocumentFragment;
      const $lightbox = $fragment.querySelector<HTMLElement>('.media__lightbox') ?? abort();
      const $container = $lightbox.querySelector<HTMLElement>('.media__lightbox-container') ?? abort();
      const $image = $container.querySelector<HTMLElement>('.media__lightbox-image') ?? abort();
    
      const dialog = new A11yDialog($lightbox);
      const resizeOberserver = new ResizeObserver(() => {
        fitImageInsideContainer($image, $container);
      });
    
      $lightbox.addEventListener('show', () => {
        fitImageInsideContainer($image, $container);
        resizeOberserver.observe($lightbox);
      });
    
      $lightbox.addEventListener('hide', () => {
        resizeOberserver.disconnect();
      });
    
      $lightbox.addEventListener('destroy', () => {
        $lightbox.remove();
      });
    
      $lightbox.addEventListener('click', (clickEvent) => {
        const { target: $target } = clickEvent;
    
        if ($target instanceof Element && $target.closest('[data-media-lightbox-action="close"]')) {
          clickEvent.preventDefault();
          dialog.destroy();
        }
      });
    
      $media.appendChild($lightbox);
      dialog.show();
    });
    
  • URL: /components/raw/media/media.ts
  • Filesystem Path: src/components/3-molecules/media/media.ts
  • Size: 1.7 KB

No notes defined.