diff --git a/src/layouts/Page.astro b/src/layouts/Page.astro
index 75c6b09..77e59b9 100644
--- a/src/layouts/Page.astro
+++ b/src/layouts/Page.astro
@@ -27,7 +27,7 @@ const OG_IMAGE = new URL('/dulmage-social.png', Astro.site).href;
---
-
+
diff --git a/src/pages/404.astro b/src/pages/404.astro
index ad74bec..7756be6 100644
--- a/src/pages/404.astro
+++ b/src/pages/404.astro
@@ -47,17 +47,23 @@ import Stars from '@components/Stars.astro';
}
}
- .ErrorContent {
+ :global(#Main404) {
--color-portfolio: hsl(var(--color-rainbow) 100% 50%);
+ animation: rainbowSpin 4s linear infinite both;
+ }
- position: relative;
+ .ErrorContent {
display: grid;
justify-content: center;
gap: var(--space-tight);
padding: var(--space);
text-align: center;
max-width: 90rem;
- animation: rainbowSpin 4s linear infinite both;
+
+ /* Page load (fade-in) */
+ position: relative;
+ z-index: var(--index-thermosphere);
+ animation: fadeIn var(--speed-slower) var(--speed-slow) var(--ease) both;
}
.ErrorContent h4 a {
diff --git a/src/pages/index.astro b/src/pages/index.astro
index 42b0d92..b23de78 100644
--- a/src/pages/index.astro
+++ b/src/pages/index.astro
@@ -4,6 +4,7 @@ import Page from '@layouts/Page.astro';
import {NAV_ID, NAV_TOGGLE_ID, OVERLAY_ID} from '@data/app';
import {sections} from '@data/sections';
+import Contact from '@components/Contact.astro';
import Hamburger from '@components/Hamburger.astro';
import Navigation from '@components/Navigation.astro';
import Project from '@components/Project.astro';
@@ -14,8 +15,9 @@ import ProjectOverlay from '@sections/ProjectOverlay.astro';
const [intro, ...portfolioSections] = sections;
---
-
+
+
diff --git a/src/scripts/PageLoad.ts b/src/scripts/PageLoad.ts
new file mode 100644
index 0000000..86cc8fa
--- /dev/null
+++ b/src/scripts/PageLoad.ts
@@ -0,0 +1,40 @@
+export type HtmlReady = 'loading' | 'done' | 'error';
+
+export class PageLoad {
+ static MOTION_DELAY = 1200;
+
+ static documentState() {
+ return document.readyState;
+ }
+
+ static isHome() {
+ const {pathname} = window.location;
+ return pathname === '' || pathname === '/';
+ }
+
+ static isLoaded() {
+ return document.documentElement.dataset.ready === 'done';
+ }
+
+ static schedule() {
+ if (PageLoad.documentState() === 'complete') {
+ PageLoad.#updateDocument();
+ return;
+ }
+
+ document.addEventListener('readystatechange', PageLoad.#handleReadyState);
+ }
+
+ static #handleReadyState() {
+ window.scrollTo(0, 0);
+ window.setTimeout(PageLoad.#updateDocument, PageLoad.MOTION_DELAY);
+ }
+
+ static #updateDocument() {
+ document.documentElement.dataset.ready = 'done';
+ document.removeEventListener(
+ 'readystatechange',
+ PageLoad.#handleReadyState,
+ );
+ }
+}
diff --git a/src/sections/Intro.astro b/src/sections/Intro.astro
index 1fd0a4e..57d2b9f 100644
--- a/src/sections/Intro.astro
+++ b/src/sections/Intro.astro
@@ -1,6 +1,5 @@
---
import {type SectionEntry} from '@data/types';
-import Contact from '@components/Contact.astro';
interface Props {
id: SectionEntry['id'];
@@ -32,8 +31,6 @@ const {id, thumbnail} = Astro.props;
Please get in touch if you have any questions. Thank you.
-
-
@@ -53,6 +50,11 @@ const {id, thumbnail} = Astro.props;
@media (--min-tablet) {
gap: var(--space);
}
+
+ /* Page load (fade-in) */
+ position: relative;
+ z-index: var(--index-thermosphere);
+ animation: fadeIn var(--speed-slower) var(--speed-slow) var(--ease) both;
}
.Details {
diff --git a/src/styles/global.css b/src/styles/global.css
index cc38de9..5c757c7 100644
--- a/src/styles/global.css
+++ b/src/styles/global.css
@@ -87,34 +87,6 @@ body {
cursor: url('../assets/svg/cursors/CursorAuto.svg'), auto;
}
-/* --- Page load --- */
-/* TODO: Consider something better with `document.readystate`. */
-
-@keyframes pageLoad {
- from {
- opacity: 1;
- visibility: visible;
- }
- to {
- opacity: 0;
- visibility: hidden;
- }
-}
-
-body {
- position: relative;
-
- &::after {
- content: '';
- z-index: var(--index-mesosphere);
- position: fixed;
- inset: 0;
- pointer-events: none;
- background-color: black;
- animation: pageLoad var(--speed-slow) var(--speed) var(--ease) forwards;
- }
-}
-
/* --- Smooth scroll + snapping --- */
/* Disabled because it breaks "dynamic chrome" behaviour on iOS */
@@ -330,3 +302,14 @@ button {
}
*/
}
+
+/* --- Global animations --- */
+
+@keyframes fadeIn {
+ from {
+ opacity: 0;
+ }
+ to {
+ opacity: 1;
+ }
+}