image zoom

This commit is contained in:
bronkuu 2026-06-02 10:13:10 +02:00
parent a891f1087a
commit 56db1b365d
5 changed files with 130 additions and 1 deletions

View file

@ -9,6 +9,7 @@
border-radius: var(--border-radius); border-radius: var(--border-radius);
transition: transform 0.3s, box-shadow 0.3s; transition: transform 0.3s, box-shadow 0.3s;
position: relative; position: relative;
cursor: pointer;
} }
& > *:hover { & > *:hover {
@ -41,3 +42,68 @@
grid-row: span 2; grid-row: span 2;
} }
} }
#lightbox {
position: fixed;
inset: 0;
z-index: 1000;
display: flex;
align-items: center;
justify-content: center;
background: rgba(0, 0, 0, 0.8);
backdrop-filter: blur(8px);
-webkit-backdrop-filter: blur(8px);
opacity: 0;
pointer-events: none;
transition: opacity 0.3s;
&.open {
opacity: 1;
pointer-events: all;
}
& > img {
max-width: min(90vw, 1200px);
max-height: 85vh;
border-radius: var(--small-radius);
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5);
object-fit: contain;
}
& > button {
position: absolute;
background: rgba(0, 0, 0, 0.5);
border: none;
color: white;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
width: 3rem;
height: 3rem;
border-radius: 50%;
transition: background 0.2s;
&:hover {
background: rgba(0, 0, 0, 0.8);
}
& svg {
width: 1.5rem;
height: 1.5rem;
}
}
& #lb-close {
top: 1.5rem;
right: 1.5rem;
}
& #lb-prev {
left: 1.5rem;
}
& #lb-next {
right: 1.5rem;
}
}

View file

@ -14,5 +14,6 @@ templ Portfolio(images []string) {
</div> </div>
</section> </section>
</main> </main>
<script defer src="portfolio.js"></script>
} }
} }

View file

@ -67,7 +67,7 @@ func Portfolio(images []string) templ.Component {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
} }
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "</div></section></main>") templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "</div></section></main><script defer src=\"portfolio.js\"></script>")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }

61
js/portfolio.js Normal file
View file

@ -0,0 +1,61 @@
(function () {
var grid = document.getElementById('portfolio-grid');
if (!grid) return;
var items = Array.from(grid.querySelectorAll(':scope > div'));
if (!items.length) return;
var lb = document.createElement('div');
lb.id = 'lightbox';
lb.innerHTML =
'<button id="lb-close" aria-label="Zamknij"><svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 6 6 18"/><path d="m6 6 12 12"/></svg></button>' +
'<button id="lb-prev" aria-label="Poprzednie"><svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m15 18-6-6 6-6"/></svg></button>' +
'<img src="" alt="">' +
'<button id="lb-next" aria-label="Następne"><svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6"/></svg></button>';
document.body.appendChild(lb);
var lbImg = lb.querySelector('img');
var current = -1;
function open(idx) {
current = idx;
var img = items[current].querySelector('img');
lbImg.src = img.src;
lbImg.alt = img.alt;
lb.classList.add('open');
}
function close() {
lb.classList.remove('open');
current = -1;
}
function prev() {
if (current < 0) return;
open((current - 1 + items.length) % items.length);
}
function next() {
if (current < 0) return;
open((current + 1) % items.length);
}
items.forEach(function (item, i) {
item.addEventListener('click', function () { open(i); });
});
lb.querySelector('#lb-close').addEventListener('click', close);
lb.querySelector('#lb-prev').addEventListener('click', function (e) { e.stopPropagation(); prev(); });
lb.querySelector('#lb-next').addEventListener('click', function (e) { e.stopPropagation(); next(); });
document.addEventListener('keydown', function (e) {
if (!lb.classList.contains('open')) return;
if (e.key === 'Escape') { close(); e.preventDefault(); }
if (e.key === 'ArrowLeft') { prev(); e.preventDefault(); }
if (e.key === 'ArrowRight') { next(); e.preventDefault(); }
});
lb.addEventListener('click', function (e) {
if (e.target === lb) close();
});
})();

View file

@ -105,6 +105,7 @@ func main() {
mergeStyles() mergeStyles()
utils.CopyFile("img/favicon.avif", "www/images/favicon.avif") utils.CopyFile("img/favicon.avif", "www/images/favicon.avif")
utils.CopyFile("img/logo.svg", "www/images/logo.svg") utils.CopyFile("img/logo.svg", "www/images/logo.svg")
utils.CopyFile("js/portfolio.js", "www/portfolio.js")
log.Println("listening on :8000") log.Println("listening on :8000")
log.Fatal(http.ListenAndServe(":8000", http.FileServer(http.Dir("www")))) log.Fatal(http.ListenAndServe(":8000", http.FileServer(http.Dir("www"))))
} }