Reserve image space to prevent loading layout shifts

This commit is contained in:
Matt Isenhower
2026-09-27 15:17:07 -07:00
parent c5c55b3dc3
commit 982e270ece
19 changed files with 78 additions and 31 deletions

View File

@@ -4,6 +4,8 @@
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="preload" href="/src/assets/fonts/Splatoon1-common.woff2" as="font" type="font/woff2" crossorigin />
<link rel="preload" href="/src/assets/fonts/Splatoon2-common.woff2" as="font" type="font/woff2" crossorigin />
<title>Splatoon3.ink</title>
<meta property="og:title" content="Splatoon 3 Schedules and Gear">
<meta property="og:description" content="Current stages, Salmon Run schedules, Splatnet Gear, and more.">

View File

@@ -2,7 +2,7 @@
<ProductContainer v-if="gear" class="pt-10 pb-4 px-10" bg="bg-zinc-500 bg-monsters">
<div class="flex flex-col items-center space-y-4">
<div>
<img :src="gear.image.url" />
<img :src="gear.image.url" width="256" height="256" />
</div>
<div>
<SquidTape class="font-splatoon2 text-2xl bg-splatoon-salmonRun -rotate-2" squid-size="16px">

View File

@@ -2,7 +2,7 @@
<ProductContainer :bg="type.bg" class="w-full pt-10 pb-4">
<div class="space-y-2">
<div class="flex items-center space-x-2 mx-2">
<img :src="type.img" />
<img :src="type.img" width="40" height="40" />
<div class="font-splatoon1 lg:text-2xl xl:text-3xl text-shadow">
{{ $t(type.name) }}
</div>

View File

@@ -4,7 +4,7 @@
<div class="relative h-full overflow-hidden">
<div class="absolute inset-x-0 bg-zinc-800/40 backdrop-blur-md z-30 pt-10 pb-4">
<div class="flex items-center space-x-2 mx-2">
<img :src="type.img" />
<img :src="type.img" width="40" height="40" />
<div class="font-splatoon1 lg:text-2xl xl:text-3xl text-shadow">
{{ $t(type.name) }}
</div>

View File

@@ -69,11 +69,11 @@
</div>
<div class="flex-1">
<StageImage class="flex-1" img-class="rounded-l-xl" text-size="text-xs" :stage="props.schedule?.settings.vsStages[0]" />
<StageImage class="w-full" img-class="rounded-l-xl" text-size="text-xs" :stage="props.schedule?.settings.vsStages[0]" />
</div>
<div class="flex-1">
<StageImage class="flex-1" img-class="rounded-r-xl" text-size="text-xs" :stage="props.schedule?.settings.vsStages[1]" />
<StageImage class="w-full" img-class="rounded-r-xl" text-size="text-xs" :stage="props.schedule?.settings.vsStages[1]" />
</div>
</div>
</div>

View File

@@ -13,7 +13,12 @@
</div>
<div>
<img :src="props.festival.image.url" loading="lazy" />
<img
:src="props.festival.image.url"
width="1740"
height="680"
loading="lazy"
/>
<div class="flex -mt-3 mb-4">
<template v-for="(team, i) in festival.teams" :key="team.id">

View File

@@ -12,7 +12,12 @@
</div>
<div>
<img :src="festival.image.url" loading="lazy" />
<img
:src="festival.image.url"
width="1740"
height="680"
loading="lazy"
/>
<div class="flex -mt-3 mb-4">
<template v-for="(team, i) in festival.teams" :key="team.id">

View File

@@ -5,7 +5,7 @@
<span class="sr-only">Close</span>
<XMarkIcon class="h-4 w-4" aria-hidden="true" />
</button>
<img v-if="imgUrl" :src="imgUrl" />
<img v-if="imgUrl" :src="imgUrl" width="800" height="450" />
</div>
<div class="absolute -top-8 w-full text-center">

View File

@@ -1,7 +1,7 @@
<template>
<button class="block relative" @click.prevent="open = true">
<div class="bg-zinc-700 aspect-2/1 overflow-hidden" :class="imgClass">
<img v-if="lowRes" :src="lowRes" />
<img v-if="lowRes" :src="lowRes" width="400" height="200" />
<div v-else class="bg-zinc-500 animate-pulse h-full" :class="imgClass">
&nbsp;
</div>

View File

@@ -2,7 +2,7 @@
<ProductContainer :bg="type.bg" class="w-full pt-10 pb-4">
<div class="space-y-2">
<div class="flex items-center space-x-2 mx-2">
<img :src="type.img" />
<img :src="type.img" width="40" height="40" />
<div class="font-splatoon1 lg:text-2xl xl:text-3xl text-shadow">
{{ $t(type.name) }}
</div>

View File

@@ -3,7 +3,7 @@
<ProductContainer :bg="type.bg" class="w-full pt-10 pb-2">
<div class="space-y-2">
<div class="flex items-center space-x-2 mx-2">
<img :src="type.img" />
<img :src="type.img" width="66" height="65" />
<div class="font-splatoon1 lg:text-2xl xl:text-3xl text-shadow">
{{ $t(`splatnet.events.${event.settings.leagueMatchEvent.id}.name`, event.settings.leagueMatchEvent.name) }}

View File

@@ -3,7 +3,7 @@
<div class="space-y-4">
<div>
<div v-if="brand" class="-mb-10">
<img :src="brand.image.url" />
<img :src="brand.image.url" width="1600" height="800" />
</div>
<div class="flex flex-col items-center -space-y-2">
<SquidTape
@@ -18,7 +18,7 @@
</SquidTape>
<div v-if="brand" class="relative -rotate-2">
<img src="@/assets/img/gesotown-daily-drop-bg.png" class="w-64" />
<img width="840" height="146" src="@/assets/img/gesotown-daily-drop-bg.png" class="w-64" />
<div class="absolute inset-0 flex items-center ml-4">
<div class="font-splatoon2 text-lg">
{{ $t(`splatnet.brands.${brand.brand.id}.name`, brand.brand.name) }}

View File

@@ -1,6 +1,6 @@
<template>
<div class="relative">
<img src="@/assets/img/gesotown-tape-blob-bg.png" />
<img width="952" height="972" src="@/assets/img/gesotown-tape-blob-bg.png" />
<div class="absolute inset-0 flex flex-col items-center justify-evenly my-4">
<!-- Gear Image -->
@@ -12,11 +12,11 @@
<div>
<div class="flex items-center space-x-px">
<div :title="$t(`splatnet.powers.${gear.primaryGearPower.__splatoon3ink_id}.name`, gear.primaryGearPower.name)" class="bg-black rounded-full">
<img :src="gear.primaryGearPower.image.url" class="h-8" />
<img :src="gear.primaryGearPower.image.url" class="h-8 w-8" />
</div>
<div v-for="(power, i) in gear.additionalGearPowers" :key="i" :title="$t(`splatnet.powers.${power.__splatoon3ink_id}.name`, power.name)" class="bg-black rounded-full">
<img :src="power.image.url" class="h-6" />
<img :src="power.image.url" class="h-6 w-6" />
</div>
</div>
</div>
@@ -24,7 +24,7 @@
<!-- Name -->
<div class="relative text-center">
<div class="mx-6">
<img src="@/assets/img/gesotown-tape.svg" />
<img width="246" height="38" src="@/assets/img/gesotown-tape.svg" />
</div>
<div class="absolute inset-0 flex items-center justify-center">
<div class="font-splatoon2 text-sm xl:text-base ss:text-lg text-shadow">
@@ -36,7 +36,7 @@
<!-- Price -->
<div class="flex items-center space-x-2">
<div>
<img src="@/assets/img/gesotown-coin.svg" />
<img width="19" height="17" src="@/assets/img/gesotown-coin.svg" />
</div>
<div class="font-splatoon1">
{{ price }}
@@ -47,7 +47,7 @@
<!-- Brand -->
<div class="absolute top-0 right-10">
<div class="relative rotate-2">
<img src="@/assets/img/gesotown-brand-bg.png" class="w-10" />
<img width="82" height="71" src="@/assets/img/gesotown-brand-bg.png" class="w-10" />
<div class="absolute inset-0 p-2">
<img :src="gear.brand.image.url" class="w-full h-full" :title="$t(`splatnet.brands.${gear.brand.id}.name`, gear.brand.name)" />
</div>

View File

@@ -14,8 +14,8 @@
</div>
<div class="flex items-center space-x-2">
<div class="bg-white h-6 aspect-square rounded-sm">
<img :src="gear.brand.image.url" :title="$t(`splatnet.brands.${gear.brand.id}.name`, gear.brand.name)" />
<div class="bg-white h-6 w-6 shrink-0 rounded-sm">
<img class="h-full w-full" :src="gear.brand.image.url" :title="$t(`splatnet.brands.${gear.brand.id}.name`, gear.brand.name)" />
</div>
<div class="flex-1 font-splatoon2 text-shadow overflow-hidden text-ellipsis whitespace-nowrap">
@@ -26,17 +26,17 @@
<div class="flex justify-between">
<div class="flex items-center space-x-px">
<div :title="$t(`splatnet.powers.${gear.primaryGearPower.__splatoon3ink_id}.name`, gear.primaryGearPower.name)" class="bg-black rounded-full">
<img :src="gear.primaryGearPower.image.url" class="h-8" />
<img :src="gear.primaryGearPower.image.url" class="h-8 w-8" />
</div>
<div v-for="(power, i) in gear.additionalGearPowers" :key="i" :title="$t(`splatnet.powers.${power.__splatoon3ink_id}.name`, power.name)" class="bg-black rounded-full">
<img :src="power.image.url" class="h-6" />
<img :src="power.image.url" class="h-6 w-6" />
</div>
</div>
<div class="flex items-center space-x-2 bg-price w-28 pl-2 -mr-px">
<div>
<img src="@/assets/img/gesotown-coin.svg" />
<img width="19" height="17" src="@/assets/img/gesotown-coin.svg" />
</div>
<div class="font-splatoon1">
{{ price }}
@@ -82,7 +82,7 @@
<div class="flex items-center space-x-2 bg-price w-28 pl-2 -mr-px">
<div>
<img src="@/assets/img/gesotown-coin.svg" />
<img width="19" height="17" src="@/assets/img/gesotown-coin.svg" />
</div>
<div class="font-splatoon1">
{{ price }}

View File

@@ -1,7 +1,14 @@
<template>
<div v-if="schedule" class="font-splatoon2 space-y-1">
<div class="flex gap-2">
<img v-if="eggstra" src="@/assets/img/modes/coop.eggstra.svg" :title="$t('salmonrun.bigrun')" class="w-6 -mr-1" />
<img
v-if="eggstra"
width="40"
height="40"
src="@/assets/img/modes/coop.eggstra.svg"
:title="$t('salmonrun.bigrun')"
class="w-6 -mr-1"
/>
<div class="text-lg text-shadow text-zinc-200 ss:hidden">
{{ $d(schedule.startTime, 'dateTimeShort') }}
@@ -25,7 +32,13 @@
v-if="schedule.isBigRun"
class="bg-zinc-800/80 text-sm text-white rounded-lg px-2 border-2 border-splatoon-bigRun"
>
<img src="@/assets/img/modes/coop.bigrun.svg" :title="$t('salmonrun.bigrun')" class="w-4 inline-block" />
<img
width="25"
height="22"
src="@/assets/img/modes/coop.bigrun.svg"
:title="$t('salmonrun.bigrun')"
class="w-4 inline-block"
/>
{{ $t('salmonrun.bigrun') }}
</div>
</div>

View File

@@ -2,24 +2,32 @@
<div>
<img
v-if="boss?.name === 'Cohozuna'"
width="420"
height="421"
src="@/assets/img/king-cohozuna.png"
:class="size"
:title="$t(`splatnet.bosses.${boss.id}.name`, boss.name)"
/>
<img
v-if="boss?.name === 'Horrorboros'"
width="420"
height="421"
src="@/assets/img/king-horrorboros.png"
:class="size"
:title="$t(`splatnet.bosses.${boss.id}.name`, boss.name)"
/>
<img
v-if="schedule.setting.boss.name === 'Megalodontia'"
width="420"
height="421"
src="@/assets/img/king-megalodontia.png"
:class="size"
:title="$t(`splatnet.bosses.${schedule.setting.boss.id}.name`, schedule.setting.boss.name)"
/>
<img
v-if="schedule.setting.boss.name === 'Triumvirate'"
width="400"
height="400"
src="@/assets/img/king-triumvirate.png"
:class="size"
:title="$t(`splatnet.bosses.${schedule.setting.boss.id}.name`, schedule.setting.boss.name)"

View File

@@ -2,8 +2,22 @@
<div v-if="schedule" class="font-splatoon2 space-y-1">
<div class="flex items-center">
<div>
<img v-if="schedule.isBigRun" src="@/assets/img/modes/coop.bigrun.svg" :title="$t('salmonrun.bigrun')" class="w-6 mr-1" />
<img v-else src="@/assets/img/modes/coop.svg" :title="$t('salmonrun.title')" class="w-6 mr-1" />
<img
v-if="schedule.isBigRun"
width="25"
height="22"
src="@/assets/img/modes/coop.bigrun.svg"
:title="$t('salmonrun.bigrun')"
class="w-6 mr-1"
/>
<img
v-else
width="40"
height="40"
src="@/assets/img/modes/coop.svg"
:title="$t('salmonrun.title')"
class="w-6 mr-1"
/>
</div>
<div class="flex-1 text-shadow text-zinc-200">

View File

@@ -20,7 +20,7 @@
<div class="m-2 text-center text-xs text-zinc-500">
<div>
<img src="@/assets/img/little-buddy.png" class="mx-auto mb-4" width="50" />
<img src="@/assets/img/little-buddy.png" class="mx-auto mb-4 w-[50px]" width="131" height="175" />
</div>
<div>
{{ $t('footer.term') }}

View File

@@ -17,7 +17,7 @@
<ProductContainer v-else :bg="type.bg" class="w-full mx-auto max-w-lg pt-10 pb-4 -rotate-1">
<div class="flex justify-center">
<div class="inline-flex items-center font-splatoon2 text-xl text-shadow m-2">
<img :src="type.img" />
<img :src="type.img" width="66" height="65" />
{{ $t('events.not_available') }}
</div>
</div>