Skip to content

Commit d3c033d

Browse files
committed
perf: improve blog and homepage image performance (lazy-loading, responsive, docs) #264
Made-with: Cursor
1 parent 9a2116e commit d3c033d

File tree

10 files changed

+38
-7
lines changed

10 files changed

+38
-7
lines changed

CONTRIBUTING.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,18 @@ dependencies and activate it.
5656
- Place a header image (either `header.png` or `header.jpg`) in your blog
5757
post folder. Make sure the image is under a free license.
5858

59+
### Authoring images (performance and accessibility)
60+
61+
- **Alt text:** Always add descriptive `alt` text for images (e.g. in Markdown:
62+
`![Description of the image](image.png)`). This helps accessibility and SEO.
63+
- **Dimensions:** Prefer images with reasonable dimensions (e.g. 1200px wide for
64+
in-content screenshots). The theme applies responsive sizing and lazy-loading
65+
to blog content images; very large originals will still be downscaled by the
66+
browser but use more bandwidth.
67+
- **Format:** PNG or JPEG is fine. For very large images, consider providing
68+
WebP versions where the build or CMS supports it; the theme can use
69+
`<picture>` / `srcset` for fallbacks.
70+
5971
### Metadata and Formatting
6072

6173
- **Markdown Posts:** Add a metadata block at the beginning of your `index.md`

theme/base.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -498,7 +498,7 @@ <h2 class="accordion-header" id="h-{{ pid }}">
498498
</div>
499499
<div class="d-flex align-items-center gap-3">
500500
<a rel="license" href="https://creativecommons.org/licenses/by-sa/4.0/">
501-
<img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by-sa/4.0/88x31.png">
501+
<img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by-sa/4.0/88x31.png" width="88" height="31" loading="lazy" decoding="async">
502502
</a>
503503
<div class="color_mode">
504504
<input type="checkbox" class="color_choice" id="mode" aria-label="Toggle color mode">

theme/blog-post.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ <h1 class="post-title">
7979
<article>
8080
<a href="{{ sub_nav_item.url|url }}" class="image">
8181
<img src="https://picsum.photos/id/{{ loop.index }}/400/200"
82-
alt="{{ sub_nav_item.title }}" />
82+
alt="{{ sub_nav_item.title }}" loading="lazy" decoding="async" width="400" height="200" />
8383
</a>
8484
<h3>{{ sub_nav_item.title }}</h3>
8585
<p>{{ sub_nav_item.summary }}</p>

theme/css/blog.css

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,3 +221,14 @@
221221

222222
/* Safety: never allow gigantic SVGs inside blog content */
223223
.blog-article .post_body svg.icon { width: 1em; height: 1em; }
224+
225+
/* Responsive images in blog content (LCP / defer offscreen images) */
226+
.blog-article .post_body img {
227+
max-width: 100%;
228+
height: auto;
229+
display: block;
230+
}
231+
.blog-article .post_body img:not([width]):not([height]) {
232+
/* Reserve space to reduce CLS when dimensions unknown */
233+
min-height: 1px;
234+
}

theme/events.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ <h2>Upcoming Events</h2>
1414
<div class="row {{ colors[loop.index % 2] }}">
1515
<div class="col-4 text-center">
1616
<a href="{{ event.url }}">
17-
<img src="{{ event.thumbnail }}" />
17+
<img src="{{ event.thumbnail }}" alt="{{ event.name }}" loading="lazy" decoding="async" />
1818
</a>
1919
</div>
2020
<div class="col-8">
@@ -47,7 +47,7 @@ <h2>Past Events</h2>
4747
<div class="row {{ colors[loop.index % 2] }}">
4848
<div class="col-4 text-center">
4949
<a href="{{ event.url }}">
50-
<img src="{{ event.thumbnail }}" />
50+
<img src="{{ event.thumbnail }}" alt="{{ event.name }}" loading="lazy" decoding="async" />
5151
</a>
5252
</div>
5353
<div class="col-8">

theme/home.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ <h2 class="section-title">Our Partners</h2>
116116
{% for partner in page.meta["partners"] %}
117117
<li class="logo-item">
118118
<a href="{{ partner.url }}" target="_blank" rel="noopener">
119-
<img src="{{ partner.logo }}" alt="{{ partner.name }}">
119+
<img src="{{ partner.logo }}" alt="{{ partner.name }}" loading="lazy" decoding="async">
120120
<span class="logo-caption">{{ partner.name }}</span>
121121
</a>
122122
</li>

theme/js/theme.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,12 @@
8484
document.querySelectorAll('.dropdown-menu.mega').forEach(menu => {
8585
menu.addEventListener('click', (e) => e.stopPropagation());
8686
});
87+
88+
/* 7) Lazy-load images in blog content (markdown-rendered imgs don't have loading attr) */
89+
document.querySelectorAll('.post_body img:not([loading])').forEach(function (img) {
90+
img.setAttribute('loading', 'lazy');
91+
img.setAttribute('decoding', 'async');
92+
});
8793
});
8894

8995
// Optional public API

theme/partners.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
<div class="logo-wrap p-4">
1919
{% if logo %}
2020
<a href="{{ site or '#' }}" class="d-inline-flex" target="_blank" rel="noopener">
21-
<img src="{{ logo }}" alt="{{ partner.name }}" />
21+
<img src="{{ logo }}" alt="{{ partner.name }}" loading="lazy" decoding="async" />
2222
</a>
2323
{% endif %}
2424
</div>

theme/projects.html

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,13 @@ <h2>
2525
<img
2626
alt="Static Badge"
2727
src="https://img.shields.io/badge/project-incubated-333333?style=for-the-badge&label=project&labelColor=FFAA00&color=888888"
28+
loading="lazy" decoding="async"
2829
/>
2930
{% elif project.type == "affiliated" %}
3031
<img
3132
alt="Static Badge"
3233
src="https://img.shields.io/badge/project-affiliated-333333?style=for-the-badge&label=project&labelColor=0E91C3&color=888888"
34+
loading="lazy" decoding="async"
3335
/>
3436
{% endif %}
3537
{{ project.name }}

theme/team.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ <h2 class="mb-3">{{ group.name }}</h2>
2525
<div class="col">
2626
<div class="card h-100">
2727
{% if member.image_url %}
28-
<img src="{{ member.image_url }}" class="card-img-top" alt="{{ member.name }}">
28+
<img src="{{ member.image_url }}" class="card-img-top" alt="{{ member.name }}" loading="lazy" decoding="async" width="400" height="400">
2929
{% endif %}
3030

3131
<div class="card-body d-flex flex-column">

0 commit comments

Comments
 (0)