web: right-size card images and load the first ones eagerly
This commit is contained in:
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>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
|||||||
@@ -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}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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 && (
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
Reference in new issue
Block a user