<div class="porthole">
<div class="porthole__images">
<img src="https://bildermangel.de/600x600/fe7c09/130f26.webp" width="600" height="600" class="porthole__image">
<img src="https://bildermangel.de/600x600/EDFF21/130f26.webp" width="600" height="600" class="porthole__image" load="lazy">
<img src="https://bildermangel.de/600x600/063971/130f26.webp" width="600" height="600" class="porthole__image" load="lazy">
<img src="https://bildermangel.de/600x600/FDF4E3/130f26.webp" width="600" height="600" class="porthole__image" load="lazy">
</div>
<div class="porthole__buttons" aria-hidden="true">
<button class="porthole__button porthole__button--prev" type="button" data-porthole="prev" title="Previous image" disabled>
<svg class="icon icon--angle-up" viewBox="0 0 200 200" aria-hidden="true">
<use xlink:href="/assets/icons/icons.dcaca1c147.svg#angle-up"></use>
</svg> </button>
<button class="porthole__button porthole__button--next" type="button" data-porthole="next" title="Next image" disabled>
<svg class="icon icon--angle-down" viewBox="0 0 200 200" aria-hidden="true">
<use xlink:href="/assets/icons/icons.dcaca1c147.svg#angle-down"></use>
</svg> </button>
</div>
</div>
<div {{ html_attributes({
id: id ?? false,
class: 'porthole',
}, attrs ?? {}) }}>
<div class="porthole__images">
{% for image in images %}
<img {{ html_attributes(image, {
class: 'porthole__image',
load: not loop.first ? 'lazy',
}) }}>
{% endfor %}
</div>
<div class="porthole__buttons" aria-hidden="true">
<button {{ html_attributes({
class: 'porthole__button porthole__button--prev',
type: 'button',
'data-porthole': 'prev',
title: 'Previous image' | t('site'),
disabled: true,
}) }}>
{% include '@icon' with {
icon: 'angle-up',
} only %}
</button>
<button {{ html_attributes({
class: 'porthole__button porthole__button--next',
type: 'button',
'data-porthole': 'next',
title: 'Next image' | t('site'),
disabled: true,
}) }}>
{% include '@icon' with {
icon: 'angle-down',
} only %}
</button>
</div>
</div>
{
"images": [
{
"src": "https://bildermangel.de/600x600/fe7c09/130f26.webp",
"width": 600,
"height": 600
},
{
"src": "https://bildermangel.de/600x600/EDFF21/130f26.webp",
"width": 600,
"height": 600
},
{
"src": "https://bildermangel.de/600x600/063971/130f26.webp",
"width": 600,
"height": 600
},
{
"src": "https://bildermangel.de/600x600/FDF4E3/130f26.webp",
"width": 600,
"height": 600
}
]
}
.porthole {
--box-shadow-color: #000;
aspect-ratio: 1;
background-color: var(--color-white);
border-radius: 50%;
box-shadow: var(--box-shadow-xxl-dense);
container-name: porthole;
container-type: inline-size;
overflow: clip;
position: relative;
}
.porthole__images {
block-size: 100cqi;
display: flex;
flex-direction: column;
overflow-x: auto;
overflow-y: none;
overscroll-behavior-inline: contain;
position: relative;
scroll-behavior: smooth;
scroll-snap-type: y mandatory;
scrollbar-width: none;
z-index: 1;
&::-webkit-scrollbar {
display: none;
}
}
.porthole__image {
aspect-ratio: 1;
inline-size: 100%;
object-fit: cover;
scroll-snap-align: start;
}
.porthole__buttons {
align-items: center;
display: flex;
flex-direction: column;
inset: 0;
justify-content: space-between;
padding: 5cqi;
pointer-events: none;
position: absolute;
z-index: 2;
}
.porthole__button {
--icon-size: 7cqi;
align-items: center;
aspect-ratio: 1;
background-color: var(--color-white);
block-size: calc(var(--icon-size) + 2cqi);
border-radius: 50%;
color: var(--color-gray-300);
display: flex;
inline-size: calc(var(--icon-size) + 2cqi);
justify-content: center;
line-height: 0;
pointer-events: all;
transition-property: color, opacity;
&:not([disabled]):is(:hover, :focus-visible) {
color: var(--color-gray-800);
}
&:is([disabled]) {
opacity: 0.5;
}
}
import abort from '../../../javascripts/utils/abort';
import onLoad from '../../../javascripts/utils/onLoad';
onLoad<HTMLElement>('.porthole', ($porthole) => {
const $images = $porthole.querySelector('.porthole__images') ?? abort();
const $prevButton = $porthole.querySelector<HTMLButtonElement>('[data-porthole="prev"]') ?? abort();
const $nextButton = $porthole.querySelector<HTMLButtonElement>('[data-porthole="next"]') ?? abort();
const onScroll = () => {
$prevButton.disabled = $images.scrollTop < $images.clientHeight;
$nextButton.disabled = $images.scrollTop > ($images.scrollHeight - $images.clientHeight * 2);
};
$images.addEventListener('scroll', onScroll, { passive: true });
onScroll();
$prevButton.addEventListener('click', (event) => {
event.preventDefault();
$images.scrollBy({ top: $images.clientHeight * -1 });
});
$nextButton.addEventListener('click', (event) => {
event.preventDefault();
$images.scrollBy({ top: $images.clientHeight });
});
});
No notes defined.