fix: artist hero uses <img> with responsive object-position for better crop

Switching from background-image (inline JS, single position for all sizes)
to an <img> element lets CSS media queries apply different object-position:
- Mobile: center top (portrait images show face in upper portion)
- Desktop: center 30% (wide banner, lower anchor avoids showing only hair)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
HoneyandClaude Sonnet 4.6 committed 2026-06-07 21:05:47 +02:00
1 parent 106fbf54bf
commit aa20eec29d
2 files changed
+9 -1

No files matched your search

+7 -1
View File
@@ -70,6 +70,7 @@ export async function loadArtistDetail(artist) {
const tsEl = document.getElementById('artist-topsongs-section'); const tsEl = document.getElementById('artist-topsongs-section');
const albEl = document.getElementById('artist-albums-section'); const albEl = document.getElementById('artist-albums-section');
hero.style.background = 'linear-gradient(135deg, var(--surface2), var(--surface))'; hero.style.background = 'linear-gradient(135deg, var(--surface2), var(--surface))';
hero.querySelector('.artist-hero-img')?.remove();
const overlay = hero.querySelector('.artist-hero-overlay'); const overlay = hero.querySelector('.artist-hero-overlay');
if(overlay) overlay.style.background = ''; if(overlay) overlay.style.background = '';
[bioEl, simEl, tsEl, albEl].forEach(el => { if(el) el.innerHTML = ''; }); [bioEl, simEl, tsEl, albEl].forEach(el => { if(el) el.innerHTML = ''; });
@@ -108,7 +109,12 @@ export async function loadArtistDetail(artist) {
// ── Hero ── // ── Hero ──
const img = imgRes.status === 'fulfilled' ? imgRes.value : null; const img = imgRes.status === 'fulfilled' ? imgRes.value : null;
if(img) { if(img) {
hero.style.background = `url('${img}') center 20%/cover no-repeat`; hero.style.background = '';
const heroImg = document.createElement('img');
heroImg.className = 'artist-hero-img';
heroImg.alt = '';
heroImg.src = img;
hero.insertBefore(heroImg, hero.firstChild);
if(overlay) overlay.style.background = 'linear-gradient(to right,rgba(7,7,15,.95) 0%,rgba(7,7,15,.35) 55%,rgba(7,7,15,.75) 100%)'; if(overlay) overlay.style.background = 'linear-gradient(to right,rgba(7,7,15,.95) 0%,rgba(7,7,15,.35) 55%,rgba(7,7,15,.75) 100%)';
} }
+2
View File
@@ -824,10 +824,12 @@ button:focus{outline:none}
.artist-hero{height:220px;border-radius:14px;overflow:hidden;position:relative;margin-bottom:24px;background:linear-gradient(135deg,var(--surface2),var(--surface))} .artist-hero{height:220px;border-radius:14px;overflow:hidden;position:relative;margin-bottom:24px;background:linear-gradient(135deg,var(--surface2),var(--surface))}
.artist-hero-overlay{position:absolute;inset:0;background:linear-gradient(to right,rgba(7,7,15,.85) 0%,transparent 100%);display:flex;align-items:flex-end;padding:20px 28px} .artist-hero-overlay{position:absolute;inset:0;background:linear-gradient(to right,rgba(7,7,15,.85) 0%,transparent 100%);display:flex;align-items:flex-end;padding:20px 28px}
.artist-hero-name{font-size:32px;font-weight:800;letter-spacing:-1px} .artist-hero-name{font-size:32px;font-weight:800;letter-spacing:-1px}
.artist-hero-img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;object-position:center top;display:block}
@media(min-width:769px){ @media(min-width:769px){
.artist-hero{height:320px;border-radius:16px} .artist-hero{height:320px;border-radius:16px}
.artist-hero-overlay{padding:28px 36px} .artist-hero-overlay{padding:28px 36px}
.artist-hero-name{font-size:46px;letter-spacing:-2px} .artist-hero-name{font-size:46px;letter-spacing:-2px}
.artist-hero-img{object-position:center 30%}
} }
/* ── MISC ── */ /* ── MISC ── */