Lay the slider controls over the picture like the Kant-IT hero in 1.11.4
Round white arrows left and right, dots bottom right with the active one as an accent bar, a small pause button and no counter - the design of the hero slider on kant-it.de. Slider and controls share a positioned shell; arrows hide on phones. New style property for the active dot colour. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
1 parent
434e89f779
commit
cef710d5db
6 files changed
+51
-9
No files matched your search
+26
-2
@@ -203,8 +203,32 @@ body.consent-open{padding-bottom:260px}
|
||||
.slider-dots{position:relative}
|
||||
@supports selector(::scroll-marker){.slider-dots:not(.slider-controlled){scroll-marker-group:after;scroll-behavior:smooth;padding-bottom:0;scrollbar-width:none;scrollbar-gutter:auto}.slider-dots:not(.slider-controlled)::-webkit-scrollbar{display:none}.slider-dots:not(.slider-controlled)>*::scroll-marker{content:'';width:12px;height:12px;border-radius:50%;background:color-mix(in srgb,var(--slider-dot,currentColor) 30%,transparent);margin:0 6px;cursor:pointer}.slider-dots>*::scroll-marker:target-current{background:var(--slider-dot,var(--accent))}.slider-dots::scroll-marker-group{display:flex;justify-content:center;align-items:center;padding:14px 0 2px}}
|
||||
.slider-controlled{scrollbar-width:none;scrollbar-gutter:auto}.slider-controlled::-webkit-scrollbar{display:none}
|
||||
.slider-controls{display:flex;align-items:center;justify-content:center;flex-wrap:wrap;gap:8px;min-height:48px;margin-top:8px;padding:4px;font:14px/1.4 system-ui,sans-serif}.slider-controls button{display:inline-flex;align-items:center;justify-content:center;min-width:44px;min-height:40px;padding:8px 12px;border:1px solid color-mix(in srgb,var(--slider-ink,#193c2d) 35%,transparent);border-radius:7px;background:var(--slider-bg,#fff);color:var(--slider-ink,#193c2d);cursor:pointer;font:inherit}.slider-controls button:focus-visible{outline:3px solid #b55b12;outline-offset:3px}.slider-controls button:hover{background:color-mix(in srgb,var(--slider-bg,#fff) 85%,var(--slider-ink,#193c2d))}.slider-controls button:disabled{opacity:.6;cursor:default}.slider-position{font-variant-numeric:tabular-nums;min-width:44px;text-align:center;color:var(--slider-ink,inherit)}.slider-control-dots{display:flex;flex-wrap:wrap;gap:3px}.slider-control-dots button{min-width:32px;padding:0;border:0;background:transparent;color:var(--slider-dot,var(--slider-ink,inherit));font-size:0}.slider-control-dots button::before{content:'';width:10px;height:10px;border-radius:50%;border:2px solid currentColor;background:transparent;transition:background-color .2s}.slider-control-dots button[aria-pressed=true]::before{background:currentColor}.slider-control-dots button:hover::before{background:color-mix(in srgb,currentColor 50%,transparent)}.slider-controls[hidden]{display:none}
|
||||
@media(max-width:650px){.slider-controls button{min-height:44px;min-width:44px}}
|
||||
/* Die Steuerung liegt auf dem Bild, wie beim Hero-Slider von kant-it.de: runde Pfeile links und
|
||||
rechts, Punkte unten rechts (der aktive als Strich in der Akzentfarbe), Pause klein unten links,
|
||||
kein Zähler. Farben kommen aus der Gestaltung des Sliders (--slider-*). */
|
||||
.slider-shell{position:relative}
|
||||
.slider-controls{position:absolute;inset:0;margin:0;padding:0;pointer-events:none;font:14px/1 system-ui,sans-serif}
|
||||
.slider-controls button{pointer-events:auto;cursor:pointer;font:inherit;padding:0;border:0;background:transparent;color:inherit}
|
||||
.slider-controls button:focus-visible{outline:3px solid var(--slider-dot-active,var(--accent));outline-offset:3px}
|
||||
.slider-controls .slider-prev,.slider-controls .slider-next{position:absolute;top:50%;transform:translateY(-50%);width:50px;height:50px;border-radius:50%;background:var(--slider-bg,rgba(255,255,255,.9));color:var(--slider-ink,var(--accent));display:flex;align-items:center;justify-content:center;font-size:0;box-shadow:0 6px 18px rgba(0,0,0,.18);transition:background-color .2s,color .2s,transform .2s}
|
||||
.slider-prev{left:24px}.slider-next{right:24px}
|
||||
.slider-prev::before,.slider-next::before{content:'';width:12px;height:12px;border-left:2px solid currentColor;border-bottom:2px solid currentColor;transform:rotate(45deg);margin-left:5px}
|
||||
.slider-next::before{transform:rotate(-135deg);margin-left:-5px}
|
||||
.slider-controls .slider-prev:hover,.slider-controls .slider-next:hover{background:var(--slider-dot-active,var(--accent));color:#fff}
|
||||
.slider-prev:disabled,.slider-next:disabled{opacity:.4;cursor:default}
|
||||
.slider-position{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}
|
||||
.slider-control-dots{position:absolute;right:70px;bottom:20px;display:flex;gap:3px}
|
||||
.slider-control-dots button{display:flex;align-items:center;justify-content:center;width:24px;height:24px;font-size:0;transition:width .25s}
|
||||
.slider-control-dots button::before{content:'';width:9px;height:9px;border-radius:99px;background:var(--slider-dot,rgba(255,255,255,.55));transition:width .25s,background-color .25s}
|
||||
.slider-control-dots button[aria-pressed=true]{width:40px}
|
||||
.slider-control-dots button[aria-pressed=true]::before{width:28px;background:var(--slider-dot-active,var(--accent))}
|
||||
.slider-control-dots button:hover::before{background:var(--slider-dot-active,var(--accent))}
|
||||
.slider-controls .slider-play{position:absolute;right:24px;bottom:16px;width:32px;height:32px;border-radius:50%;background:rgba(0,0,0,.35);color:#fff;font-size:0;display:flex;align-items:center;justify-content:center}
|
||||
.slider-play::before{content:'';width:0;height:0;border-left:9px solid currentColor;border-top:6px solid transparent;border-bottom:6px solid transparent;margin-left:2px}
|
||||
.slider-play[data-playing=true]::before{width:8px;height:11px;border:0;border-left:3px solid currentColor;border-right:3px solid currentColor;margin-left:0}
|
||||
.slider-play:disabled{opacity:.4;cursor:default}
|
||||
.slider-controls[hidden]{display:none}
|
||||
@media(max-width:600px){.slider-controls .slider-prev,.slider-controls .slider-next{display:none}.slider-control-dots{right:54px;bottom:14px}.slider-controls .slider-play{right:14px;bottom:12px}}
|
||||
|
||||
.slide-desktop-1{grid-auto-columns:100%}.slide-desktop-2{grid-auto-columns:calc(50% - 10px)}
|
||||
.slide-desktop-3{grid-auto-columns:calc(33.333% - 14px)}.slide-desktop-4{grid-auto-columns:calc(25% - 15px)}
|
||||
|
||||
+10
-5
@@ -56,9 +56,9 @@ export function initSliders(doc = document) {
|
||||
go(direction > 0 ? (last ? visible[0] : visible[Math.min(visible.length - 1, position + 1)]) : (first ? visible.at(-1) : visible[Math.max(0, position - 1)]));
|
||||
};
|
||||
const manual = action => { playing = false; clearTimeout(timer); update(); action(); };
|
||||
const previous = button('←', 'Vorherige Folie', () => manual(() => step(-1)));
|
||||
const previous = button('←', 'Vorherige Folie', () => manual(() => step(-1))); previous.className = 'slider-prev';
|
||||
const count = doc.createElement('span'); count.className = 'slider-position'; controls.append(count);
|
||||
const next = button('→', 'Nächste Folie', () => manual(() => step(1)));
|
||||
const next = button('→', 'Nächste Folie', () => manual(() => step(1))); next.className = 'slider-next';
|
||||
const dots = [];
|
||||
if (slider.classList.contains('slider-dots')) {
|
||||
const group = doc.createElement('div'); group.className = 'slider-control-dots'; controls.append(group);
|
||||
@@ -67,6 +67,7 @@ export function initSliders(doc = document) {
|
||||
});
|
||||
}
|
||||
const play = seconds >= 3 ? button('', 'Automatische Wiedergabe pausieren', () => { playing = !playing; update(); schedule(); }) : null;
|
||||
if (play) play.className = 'slider-play';
|
||||
const update = () => {
|
||||
const visible = available();
|
||||
const fits = visible.length < 2 || slider.scrollWidth <= slider.clientWidth + 2;
|
||||
@@ -74,7 +75,7 @@ export function initSliders(doc = document) {
|
||||
const index = active(); count.textContent = `${Math.max(0, visible.indexOf(index) + 1)} / ${visible.length}`;
|
||||
dots.forEach((dot, i) => { dot.hidden = !visible.includes(i); dot.setAttribute('aria-pressed', String(i === index)); });
|
||||
if (play) {
|
||||
play.textContent = playing ? 'Pause' : 'Wiedergabe';
|
||||
play.textContent = playing ? 'Pause' : 'Wiedergabe'; play.dataset.playing = String(playing);
|
||||
play.setAttribute('aria-label', playing ? 'Automatische Wiedergabe pausieren' : 'Automatische Wiedergabe starten');
|
||||
play.disabled = reduced(); play.title = reduced() ? 'Automatik ist bei reduzierter Bewegung deaktiviert.' : '';
|
||||
}
|
||||
@@ -84,7 +85,11 @@ export function initSliders(doc = document) {
|
||||
if (playing && !reduced()) timer = setTimeout(() => { if (playing && !hover && visible && !doc.hidden) step(1); schedule(); }, seconds * 1000);
|
||||
};
|
||||
const pause = () => { playing = false; update(); clearTimeout(timer); };
|
||||
slider.after(controls); slider.classList.add('slider-controlled'); update();
|
||||
// Slider and controls share a positioned shell, so arrows and dots can lie on the picture
|
||||
// the way the Kant-IT hero slider draws them.
|
||||
const shell = doc.createElement('div'); shell.className = 'slider-shell';
|
||||
slider.replaceWith(shell); shell.append(slider, controls);
|
||||
slider.classList.add('slider-controlled'); update();
|
||||
slider.addEventListener('scroll', update, { passive: true, signal });
|
||||
view.addEventListener('resize', update, { passive: true, signal });
|
||||
slider.addEventListener('pointerenter', () => { hover = true; }, { signal });
|
||||
@@ -98,7 +103,7 @@ export function initSliders(doc = document) {
|
||||
const resize = new view.ResizeObserver(update); resize.observe(slider);
|
||||
preference.addEventListener('change', () => { if (reduced()) pause(); update(); }, { signal });
|
||||
schedule();
|
||||
cleanups.push(() => { clearTimeout(timer); clearInterval(settle); slider.style.scrollSnapType = ''; events.abort(); observer.disconnect(); resize.disconnect(); controls.remove(); slider.classList.remove('slider-controlled'); delete slider.dataset.enhanced; });
|
||||
cleanups.push(() => { clearTimeout(timer); clearInterval(settle); slider.style.scrollSnapType = ''; events.abort(); observer.disconnect(); resize.disconnect(); controls.remove(); shell.replaceWith(slider); slider.classList.remove('slider-controlled'); delete slider.dataset.enhanced; });
|
||||
});
|
||||
return () => cleanups.forEach(cleanup => cleanup());
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user