diff --git a/public/CNAME b/public/CNAME
deleted file mode 100644
index 56bdaab..0000000
--- a/public/CNAME
+++ /dev/null
@@ -1 +0,0 @@
-www.victorwesterlund.com
\ No newline at end of file
diff --git a/public/assets/css/fonts.css b/public/assets/css/fonts.css
deleted file mode 100644
index afd0844..0000000
--- a/public/assets/css/fonts.css
+++ /dev/null
@@ -1,17 +0,0 @@
-@font-face {
- font-family: "Roboto Mono";
- font-weight: 400;
- src: local("Roboto Mono Regular"),
- local("RobotoMono-Regular"),
- url("../fonts/RobotoMono-Regular.woff2"),
- url("../fonts/RobotoMono-Regular.ttf");
-}
-
-@font-face {
- font-family: "Roboto Mono";
- font-weight: 700;
- src: local("Roboto Mono Bold"),
- local("RobotoMono-Bold"),
- url("../fonts/RobotoMono-Bold.woff2"),
- url("../fonts/RobotoMono-Bold.ttf");
-}
\ No newline at end of file
diff --git a/public/assets/css/style.css b/public/assets/css/style.css
index 1da6436..5615b1f 100644
--- a/public/assets/css/style.css
+++ b/public/assets/css/style.css
@@ -1,15 +1,43 @@
-@import url("fonts.css");
-
+/* Copyright © Victor Westerlund - No libraries! 😲 */
:root {
--comp-background: 255,255,255;
- --comp-highlight: 244,242,255;
- --comp-accent: 33,33,33;
+ --comp-contrast: 33,33,33;
+ --comp-accent: 22,183,255;
--color-background: rgb(var(--comp-background));
- --color-highlight: rgb(var(--comp-highlight));
+ --color-contrast: rgb(var(--comp-contrast));
--color-accent: rgb(var(--comp-accent));
- --page-padding: 5vw;
+ --padding: 20px;
+ --border-radius: 10px;
+}
+
+.dark {
+ --comp-background: 33,33,33;
+ --comp-contrast: 255,255,255;
+ --comp-accent: 255,255,255;
+
+ --color-background: rgb(var(--comp-background));
+ --color-contrast: rgb(var(--comp-contrast));
+ --color-accent: rgb(var(--comp-accent));
+}
+
+@font-face {
+ font-family: "Roboto Mono";
+ font-weight: 400;
+ src: local("Roboto Mono Regular"),
+ local("RobotoMono-Regular"),
+ url("../fonts/RobotoMono-Regular.woff2"),
+ url("../fonts/RobotoMono-Regular.ttf");
+}
+
+@font-face {
+ font-family: "Roboto Mono";
+ font-weight: 700;
+ src: local("Roboto Mono Bold"),
+ local("RobotoMono-Bold"),
+ url("../fonts/RobotoMono-Bold.woff2"),
+ url("../fonts/RobotoMono-Bold.ttf");
}
/* -- Cornerstones -- */
@@ -17,7 +45,7 @@
* {
margin: 0;
font-family: "Roboto Mono","Arial",sans-serif;
- color: var(--color-accent);
+ color: var(--color-contrast);
}
*::selection {
@@ -26,17 +54,51 @@
}
html,
-body,
-main,
-main > div {
+body {
width: 100%;
height: 100%;
+ overflow: hidden;
+}
+
+main {
+ width: 200vw;
+ height: 100%;
+ overflow: hidden;
+ display: flex;
+}
+
+main.active {
+ transform: translateX(-100vw);
+}
+
+/* ---- */
+
+.screen {
+ width: 100vw;
+ background-color: var(--color-background);
+ display: flex;
+ flex-direction: column;
+}
+
+.screen .content {
+ box-sizing: border-box;
+ padding: calc(var(--padding) * 1.5);
+ padding-top: 0;
+ flex-grow: 1;
+}
+
+/* -- Positioning -- */
+
+.center {
+ display: flex;
+ justify-content: center;
+ align-items: center;
}
/* ---- */
.logo {
- --size: 5em;
+ --size: 1em;
--skew: calc(var(--size) / 1.7);
width: 0;
@@ -51,192 +113,100 @@ main > div {
border-top: var(--size) solid rgba(var(--comp-accent),.3);
}
-h1 {
- font-size: 2em;
-}
-
-h2 {
- font-weight: normal;
- font-size: 1.42em;
-}
-
-h2 span {
- color: var(--color-background);
- background-color: var(--color-accent);
-}
-
-/* -- Layout -- */
-
-main {
- --grid-spacing: 3vh;
-
- margin: auto;
- max-width: 200vh;
- background: radial-gradient(circle, rgba(var(--comp-accent),.2) .1vh, var(--color-background) .1vh),url("../img/pattern.gif");
- background-size: var(--grid-spacing) var(--grid-spacing),auto 90%;
- background-position: 100% 100%;
- background-repeat: repeat,no-repeat;
- background-blend-mode: multiply;
- image-rendering: pixelated;
- image-rendering: -moz-crisp-edges;
-}
-
-main * {
- image-rendering: initial;
-}
-
-main > div {
- position: absolute;
- width: 50%;
- height: 100%;
-}
-
/* ---- */
-#intro {
- left: 0;
- width: 100vh;
+.button {
+ background-color: var(--color-contrast);
+ text-align: center;
+ padding: 25px;
+ border-radius: var(--border-radius);
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ gap: var(--padding);
+}
+
+.button svg {
+ pointer-events: none;
+ fill: var(--color-contrast);
+ transform: scale(1.2);
+}
+
+.button p {
+ pointer-events: none;
+ font-size: clamp(16px,5vw,22px);
+ color: var(--color-background);
+}
+
+.button.phantom {
+ background-color: rgba(var(--comp-contrast),.1);
+}
+
+.button.phantom p {
+ color: var(--color-contrast);
+}
+
+/* -- Screens -- */
+
+header {
+ --size: 100px;
box-sizing: border-box;
- padding: var(--page-padding);
+ padding: var(--padding);
+ height: var(--size);
display: flex;
align-items: center;
- z-index: 1;
+ gap: var(--padding);
+ font-weight: bold;
}
-#intro .inner {
- display: flex;
- height: 100%;
- flex-direction: column;
- justify-content: space-between;
+header .hamburger {
+ width: calc(var(--size) - (var(--padding) * 2));
+ height: calc(var(--size) - (var(--padding) * 2));
+ box-sizing: border-box;
+ flex-shrink: 0;
+ padding: 15px;
}
-#intro .logo {
- --size: 7vh;
- margin-bottom: calc(var(--page-padding) / 2);
-}
-
-#intro .block {
+header .hamburger div {
width: 100%;
- font-size: 3vh;
+ height: 2px;
+ background: var(--color-contrast);
+ box-shadow: 0 -10px 0 0 var(--color-contrast), 0 10px 0 0 var(--color-contrast);
}
-#intro .block:last-child {
- display: flex;
- align-items: flex-end;
+header .hamburger svg {
+ fill: none;
+ stroke: var(--color-contrast);
+ stroke-linecap: round;
+ stroke-width: 2;
}
-#intro .block p {
- font-size: .7em;
- margin-bottom: 1.5em;
-}
-
-#intro .block p span {
- margin-right: .9em;
- background-color: var(--color-background);
-}
-
-/* ---- */
-
-nav a {
- text-decoration: none;
- margin-right: 2em;
- font-size: .9em;
-}
-
-nav a::after {
- content: "→";
- padding-left: .5em;
-}
-
-/* ---- */
-
-#myface {
- right: 0;
- width: 50%;
- display: flex;
- justify-content: center;
-}
-
-#myface picture,
-#myface img {
- position: absolute;
+header .spacer {
+ width: 1px;
height: 80%;
- bottom: 0;
- pointer-events: none;
+ background-color: rgba(var(--comp-contrast),.2);
+}
+
+.dark header .spacer {
+ background-color: black;
+}
+
+header .logo {
+ --size: 25px;
+ margin-top: calc(var(--size) / 2);
+ margin-right: calc(var(--size) / 2);
+}
+
+/* -- Screen > Landingpage -- */
+
+/* -- Screen > Menu -- */
+
+.screen.menu .content {
display: flex;
- justify-content: center;
+ flex-direction: column;
+ gap: 20px;
}
-#myface img {
- height: 100%;
-}
-
-/* -- Size Queries -- */
-
-@media (max-width: 1100px) {
- :root {
- --page-padding: 50px;
- }
-
- h1 {
- font-size: 7vw;
- }
-
- h2 {
- font-size: 5vw;
- }
-
- /* ---- */
-
- main {
- max-width: unset;
- background-position: 100% 0;
- background-size: var(--grid-spacing) var(--grid-spacing), auto 100vw;
- }
-
- /* ---- */
-
- #intro {
- width: initial;
- }
-
- #intro .logo {
- --size: 10vw;
- }
-
- #intro p {
- text-align: left;
- }
-
- #intro .block p:last-of-type {
- text-align: initial;
- }
-
- #myface {
- display: none;
- }
-
- /* ---- */
-
- nav a {
- text-decoration: none;
- margin-right: 5vw;
- font-size: 5vw;
- }
-}
-
-/* -- Accessibility -- */
-
-@media (hover: hover) {
- nav a:hover {
- background: var(--color-highlight);
- font-weight: bold;
- }
-}
-
-@media (prefers-color-scheme: dark) {
- :root {
- --comp-background: 0,0,0;
- --comp-accent: 255,255,255;
- }
-}
+.screen.menu .button[data="contact"] {
+ margin-top: auto;
+}
\ No newline at end of file
diff --git a/public/assets/js/script.js b/public/assets/js/script.js
index 656c4d3..724b772 100644
--- a/public/assets/js/script.js
+++ b/public/assets/js/script.js
@@ -1,19 +1,12 @@
-// Register SW if supported by browser
-if(navigator.serviceWorker) {
- navigator.serviceWorker.register("sw.js",{
- scope: "/"
- });
+function toggleMenu() {
+ const speed = 200;
+ const menu = document.getElementsByTagName("main")[0];
+
+ menu.style.setProperty("transition",`${speed}ms`);
+ menu.classList.toggle("active");
+ setTimeout(() => menu.style.removeProperty("transition"),speed + 1);
}
-const theme = window.matchMedia("(prefers-color-scheme: dark)");
-
-// Set theme color
-function updateTheme() {
- // Get theme color from stylesheet
- const color = window.getComputedStyle(document.body).getPropertyValue("--color-background");
- document.querySelector("meta[name='theme-color']").setAttribute("content",color);
-}
-
-// Set theme color and listen for changes
-theme.addEventListener("change",updateTheme);
-updateTheme(theme);
+for(const element of document.getElementsByClassName("hamburger")) {
+ element.addEventListener("click",() => toggleMenu());
+}
\ No newline at end of file
diff --git a/public/index.html b/public/index.html
index 5259755..03ca4df 100644
--- a/public/index.html
+++ b/public/index.html
@@ -1,4 +1,5 @@
+
@@ -11,34 +12,37 @@
-
-
-
-
-
victor westerlund
-
full-stack web developer
-
-
-
I create things with code. The things I've created for the public reside as open-source repositories on GitHub , the rest you'll be lucky to hear about some day.
-
Other topics (seemingly irrelevant to programming) I find facinating include but is in no way limited to astronomy, psychology, sociology, economics, ...
-
hello@victorwesterlund.com (PGP Key )
-
-
-
-
- github
-
+
+
+
+
+
+ victor westerlund
+
+
-
-
-
-
-
-
-
-
+
diff --git a/public/sw.js b/public/sw.js
deleted file mode 100644
index c2b2541..0000000
--- a/public/sw.js
+++ /dev/null
@@ -1,102 +0,0 @@
-const version = "1628250171";
-const root = "/";
-
-let activeCaches = [
- `content-${version}`
-];
-
-let cacheManifest = [
- "index.html",
- "assets/css/style.css",
- "assets/css/fonts.css",
- "assets/img/favicon.png",
- "assets/img/pattern.gif",
- "assets/fonts/RobotoMono-Bold.woff2",
- "assets/fonts/RobotoMono-Regular.woff2",
- "assets/js/script.js"
-];
-
-// Download assets and install ServiceWorker
-self.addEventListener("install", event => {
- event.waitUntil(
- caches.open(`content-${version}`).then(cache => cache.addAll(cacheManifest.map(asset => {
- // Append the root path to all assets
- return root + asset;
- })))
- )
-});
-
-// Wipe old assets from Cache Storage
-self.addEventListener("activate", event => {
- event.waitUntil(
- // Delete inactive caches
- caches.keys().then(cacheNames => {
- return Promise.all(
- cacheNames.map(cacheName => {
- if(!activeCaches.includes(cacheName)) {
- return caches.delete(cacheName);
- }
- })
- )
- })
- )
-});
-
-// Fetch and cache an asset not defined in the manifest
-async function fetchToCache(event) {
- const networkFetch = fetch(event.request);
-
- event.waitUntil(
- networkFetch.then(response => {
- const responseClone = response.clone();
- caches.open("bucket").then(cache => cache.put(event.request, responseClone));
- })
- );
-
- const response = await caches.match(event.request);
- return response || networkFetch;
-}
-
-// Fetch and follow redirects without caching
-async function fetchContent(url,i = 0) {
- if(i >= 5) {
- throw new Error("ERR_TOO_MANY_REDIRECTS");
- }
-
- return await fetch(url).then(response => {
- if(response.redirected) {
- i++;
- return fetchContent(response.url,i);
- }
- return response;
- });
-}
-
-self.addEventListener("fetch", event => {
- const url = new URL(event.request.url);
- const origin = (url.origin == location.origin) ? true : false; // Is same-origin
-
- // Speed up TTFB by serving index file first
- if(origin && url.pathname == "/") {
- event.respondWith(caches.match(root + "index.html"));
- return;
- }
-
- // Fetch cross-origin content using the network
- if(!origin || (url.pathname.substring(1,7) != "assets")) {
- event.respondWith(fetchContent(url.href));
- return;
- }
-
- // Get pattern.gif from generator. Fallback to cache on failure
- if(origin && url.pathname.endsWith("pattern.gif")) {
- const pattern = new Request(`${location.origin}${root}assets/img/pattern.php`);
- event.respondWith(fetch(pattern).catch(() => caches.match(root + "assets/img/pattern.gif")));
- return;
- }
-
- // Respond with content from cache or fetch and save
- event.respondWith(
- caches.match(event.request).then(response => response || fetchToCache(event))
- );
-});