web: right-size card images and load the first ones eagerly

This commit is contained in:
ponas committed 2026-10-14 02:02:26 +02:00
1 parent 4c05c3c8c3
commit e3e4a613c5
6 files changed
+61 -9

No files matched your search

@@ -35,8 +35,10 @@ import "./swiper.scss";
const Slide = ({ const Slide = ({
item: maskedItem, item: maskedItem,
priority,
}: { }: {
item: FragmentType<typeof ImageSliderItemFragmentDefinition>; item: FragmentType<typeof ImageSliderItemFragmentDefinition>;
priority?: boolean;
}) => { }) => {
const item = unmaskFragment(ImageSliderItemFragmentDefinition, maskedItem); const item = unmaskFragment(ImageSliderItemFragmentDefinition, maskedItem);
const image = unmaskFragment(ImageFragmentDefinition, item.image); const image = unmaskFragment(ImageFragmentDefinition, item.image);
@@ -50,6 +52,8 @@ const Slide = ({
attribution={image.attribution} attribution={image.attribution}
caption={item.text} caption={item.text}
sizes="100vw" sizes="100vw"
loading={priority ? "eager" : undefined}
fetchPriority={priority ? "high" : undefined}
/> />
); );
}; };
@@ -83,7 +87,7 @@ export const ImageSliderBlock = ({
} }
return ( return (
<SwiperSlide key={index}> <SwiperSlide key={index}>
<Slide item={item} /> <Slide item={item} priority={hero && index === 0} />
</SwiperSlide> </SwiperSlide>
); );
})} })}
+10 -1
View File
@@ -19,6 +19,15 @@ import {
const DATE_PILLS_TO_SHOW = 2; const DATE_PILLS_TO_SHOW = 2;
// How wide the image is shown, so the browser can pick a file that fits.
// "large" follows the list grid (three, two, then one column); the other two
// are thumbnails, except "small" in the wide calendar grid
const IMAGE_SIZES = {
large: "(max-width: 700px) calc(100vw - 2rem), (max-width: 1200px) 50vw, 30vw",
medium: "192px",
small: "(max-width: 700px) 192px, 15vw",
};
export const EventItem = ({ export const EventItem = ({
event, event,
mode, mode,
@@ -60,7 +69,7 @@ export const EventItem = ({
alt={featuredImage.alt} alt={featuredImage.alt}
width={0} width={0}
height={0} height={0}
sizes="(max-width: 900px) calc(100vw - 2rem), 30vw" sizes={IMAGE_SIZES[size ?? "large"]}
loading={imageLoading} loading={imageLoading}
fetchPriority={imageFetchPriority} fetchPriority={imageFetchPriority}
/> />
+18 -2
View File
@@ -4,7 +4,17 @@ import { NewsFragment, NewsListItemFragment } from "@/lib/news";
import { formatDate } from "@/lib/date"; import { formatDate } from "@/lib/date";
import Link from "next/link"; import Link from "next/link";
export const NewsItem = ({ news }: { news: NewsFragment | NewsListItemFragment }) => { export const NewsItem = ({
news,
wide,
priority,
}: {
news: NewsFragment | NewsListItemFragment;
// one of the half-width cards at the top of the list on wide screens
wide?: boolean;
// above the fold: load the image right away
priority?: boolean;
}) => {
const featuredImage: any = news.featuredImage; const featuredImage: any = news.featuredImage;
return ( return (
@@ -16,7 +26,13 @@ export const NewsItem = ({ news }: { news: NewsFragment | NewsListItemFragment }
alt={featuredImage.alt} alt={featuredImage.alt}
width={featuredImage.width} width={featuredImage.width}
height={featuredImage.height} height={featuredImage.height}
sizes="(max-width: 600px) 25vw, 55vw" sizes={
wide
? "(max-width: 600px) 25vw, 50vw"
: "(max-width: 600px) 25vw, (max-width: 900px) 50vw, 25vw"
}
loading={priority ? "eager" : undefined}
fetchPriority={priority ? "high" : undefined}
/> />
)} )}
</div> </div>
+9 -2
View File
@@ -55,8 +55,15 @@ export const NewsList = ({
<SectionHeader heading={heading} link="/aktuelt" linkText="Se flere artikler" /> <SectionHeader heading={heading} link="/aktuelt" linkText="Se flere artikler" />
)} )}
<ul className={`${styles.newsList} ${featured && styles.featured}`}> <ul className={`${styles.newsList} ${featured && styles.featured}`}>
{shown.map((singleNews) => ( {shown.map((singleNews, index) => (
<NewsItem key={singleNews.id} news={singleNews} /> <NewsItem
key={singleNews.id}
news={singleNews}
// the first two cards are half-width; on /aktuelt they are also
// the first thing on the page
wide={index < 2}
priority={!featured && index < 2}
/>
))} ))}
</ul> </ul>
{!featured && knownTotal > items.length && ( {!featured && knownTotal > items.length && (
+10 -1
View File
@@ -3,7 +3,14 @@ import styles from "./venueItem.module.scss";
import Link from "next/link"; import Link from "next/link";
import { Image } from "@/components/general/Image"; import { Image } from "@/components/general/Image";
export const VenueItem = ({ venue }: { venue: VenueFragment }) => { export const VenueItem = ({
venue,
priority,
}: {
venue: VenueFragment;
// above the fold: load the image right away
priority?: boolean;
}) => {
const featuredImage: any = venue.featuredImage; const featuredImage: any = venue.featuredImage;
const { capacitySitting, capacityStanding, usedFor } = venue; const { capacitySitting, capacityStanding, usedFor } = venue;
@@ -27,6 +34,8 @@ export const VenueItem = ({ venue }: { venue: VenueFragment }) => {
width={0} width={0}
height={0} height={0}
sizes="(max-width: 600px) 100vw, (max-width: 900px) 50vw, 35vw" sizes="(max-width: 600px) 100vw, (max-width: 900px) 50vw, 35vw"
loading={priority ? "eager" : undefined}
fetchPriority={priority ? "high" : undefined}
/> />
)} )}
</div> </div>
+9 -2
View File
@@ -6,9 +6,12 @@ import { SectionHeader } from "../general/SectionHeader";
export const VenueList = ({ export const VenueList = ({
venues, venues,
heading, heading,
priority,
}: { }: {
venues: VenueFragment[]; venues: VenueFragment[];
heading?: string; heading?: string;
// the list is the first thing on the page: load its first row right away
priority?: boolean;
}) => { }) => {
return ( return (
<div> <div>
@@ -16,8 +19,12 @@ export const VenueList = ({
<SectionHeader heading={heading} /> <SectionHeader heading={heading} />
)} )}
<ul className={styles.venueList}> <ul className={styles.venueList}>
{venues.map((venue) => ( {venues.map((venue, index) => (
<VenueItem key={venue.id} venue={venue} /> <VenueItem
key={venue.id}
venue={venue}
priority={priority && index < 3}
/>
))} ))}
</ul> </ul>
</div> </div>