aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Dockerfile6
-rw-r--r--static/style.css56
-rw-r--r--templates/gallery.html24
3 files changed, 60 insertions, 26 deletions
diff --git a/Dockerfile b/Dockerfile
index 3b11c37..015075e 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -2,10 +2,12 @@ FROM alpine
RUN apk add --no-cache python3 uv
WORKDIR /app
+COPY pyproject.toml .python-version uv.lock /app/
+RUN uv sync
+
COPY static /app/static
COPY templates /app/templates
-COPY app.py pyproject.toml .python-version uv.lock /app/
-RUN uv sync
+COPY app.py /app/
EXPOSE 8000
diff --git a/static/style.css b/static/style.css
index 1d412c1..223c62a 100644
--- a/static/style.css
+++ b/static/style.css
@@ -3,8 +3,8 @@ body {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
background-color: #121212;
color: #e0e0e0;
- margin: auto;
max-width: 1000px;
+ margin: auto;
padding: 20px;
}
@@ -22,7 +22,7 @@ h2 {
padding-bottom: 8px;
}
-/* Flexible, wrap-aligned image gallery */
+/* Flex-based gallery layout */
.gallery {
display: flex;
flex-wrap: wrap;
@@ -30,49 +30,65 @@ h2 {
align-items: flex-start;
}
-/* Gallery item constrains to image width */
+/* Each image container wraps to its image's width */
.gallery-item {
display: inline-block;
margin: 0;
+ padding: 0;
box-sizing: border-box;
overflow: hidden;
vertical-align: top;
}
-/* Image: fixed height, natural width */
+/* Image styling with placeholder skeleton */
.gallery-item img {
- display: block;
height: 200px;
width: auto;
max-width: 100vw;
object-fit: cover;
+ display: block;
transition: transform 0.2s ease-in-out;
}
-/* Description: match image width */
+.gallery-item img.loading {
+ background: linear-gradient(90deg, #222 25%, #333 50%, #222 75%);
+ background-size: 200% 100%;
+ animation: shimmer 1.5s infinite;
+ min-width: 200px;
+ min-height: 200px;
+}
+
+/* Shimmer animation for loading placeholder */
+@keyframes shimmer {
+ 0% {
+ background-position: -200% 0;
+ }
+ 100% {
+ background-position: 200% 0;
+ }
+}
+
+/* Description styling */
.gallery-item p {
margin: 8px 0 0;
font-size: 0.85rem;
color: #aaaaaa;
line-height: 1.4;
- max-width: 100%;
- white-space: normal;
+ text-align: left;
word-break: break-word;
- overflow-wrap: break-word;
- display: block;
-}
-
-/* Hover effect */
-.gallery-item img:hover {
- transform: scale(1.03);
+ max-width: 100%;
}
-/* Mobile: full width per row */
+/* Responsive layout for mobile */
@media (max-width: 600px) {
body {
padding: 12px;
}
+ h1 {
+ font-size: 1.5rem;
+ }
+
h2 {
font-size: 1.2rem;
}
@@ -89,10 +105,16 @@ h2 {
.gallery-item img {
width: 100%;
height: auto;
- //max-height: 300px;
+ max-height: 300px;
}
.gallery-item p {
padding: 0 8px 8px;
}
}
+
+/* Instagram icon link */
+.ig-link {
+ margin-left: 12px;
+ vertical-align: middle;
+}
diff --git a/templates/gallery.html b/templates/gallery.html
index b5447e2..f33c422 100644
--- a/templates/gallery.html
+++ b/templates/gallery.html
@@ -2,10 +2,6 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
- <link
- rel="stylesheet"
- href="{{ url_for('static', filename='style.css') }}"
- />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta
name="description"
@@ -21,6 +17,13 @@
<meta property="og:image" content="{{ cover_img_url }}" />
<meta property="og:url" content="{{ base_url }}" />
<meta property="og:type" content="website" />
+
+ <title>Leo Lalla</title>
+ <link
+ rel="stylesheet"
+ href="{{ url_for('static', filename='style.css') }}"
+ />
+
<script>
function layout() {
const isMobile =
@@ -30,8 +33,15 @@
const img = item.querySelector("img");
if (!img) return;
+ const cleanup = () => img.classList.remove("loading");
+
+ if (img.complete) {
+ cleanup();
+ } else {
+ img.addEventListener("load", cleanup, { once: true });
+ }
+
if (isMobile) {
- // On mobile, reset any previously set width
item.style.width = "";
return;
}
@@ -52,6 +62,7 @@
window.addEventListener("resize", layout);
</script>
</head>
+
<body>
<h1>
{{ author }} {% if ig_link %}
@@ -66,7 +77,6 @@
{% endif %}
</h1>
- <!-- -->
{% for date in dates %}
<h2>{{ date }}</h2>
<div class="gallery">
@@ -78,8 +88,8 @@
>
<img
src="{{ url_for('serve_thumbnail', filename=f.thumbnail.split('/')[-1]) }}"
- alt="{{ f.name }}"
loading="lazy"
+ class="loading"
/>
</a>
{% if f.description %}