From 13f6399fc0889ebfa9125595af415af9fb610d85 Mon Sep 17 00:00:00 2001 From: brulijam Date: Mon, 25 Nov 2024 00:26:13 +0100 Subject: [PATCH] add 38c3 theming --- src/content/links.json | 4 +- src/css/main.css | 154 ++++++++++++++++++++++++++++++++--------- src/index.html | 3 +- src/js/background.js | 105 ++++++++++++++++++++++++++++ src/js/blobs.js | 103 +++++++++++++++++++++++++++ 5 files changed, 334 insertions(+), 35 deletions(-) create mode 100644 src/js/background.js create mode 100644 src/js/blobs.js diff --git a/src/content/links.json b/src/content/links.json index effd818..ad67b7c 100644 --- a/src/content/links.json +++ b/src/content/links.json @@ -127,8 +127,8 @@ "group": 2 }, { - "name": "source code", - "href": "https://git.brulijam.com/brulijam/introduction-website", + "name": "source code (38c3 branch)", + "href": "https://git.brulijam.com/brulijam/introduction-website/src/branch/38c3-theme", "group": "footer" }, { diff --git a/src/css/main.css b/src/css/main.css index 13ddb22..3969538 100644 --- a/src/css/main.css +++ b/src/css/main.css @@ -1,22 +1,45 @@ /* Root Variables */ :root { - --bg-color: rgb(15, 15, 15); - --primary: rgb(240, 240, 240); - --secondary-color: hsl(210, 80%, 80%); - --secondary-color2: hsl(210, 60%, 40%); - --secondary-color-bg: hsl(210, 40%, 5%); --font-weight: 350; - --font-family: "Lucida Console"; + --font-family: 'space-mono'; --bigger-font-weight: 700; --link-border-radius: 1000px; --page-max-width: 700px; + + --color-primary: #FF5053; + --color-highlight: #FEF2FF; + --color-accent-a: #B2AAFF; + --color-accent-b: #6A5FDB; + --color-accent-c: #29114C; + --color-accent-d: #261A66; + --color-accent-e: #190B2F; + --color-background: #0F000A; +} + +@font-face { + font-family: 'pilowlava'; + /*src: URL('../fonts/pilowlava/Fonts/webfonts/Pilowlava-Regular.woff2') format('woff2');*/ + src: url('../fonts/pilowlava/Fonts/webfonts/Pilowlava-Regular.woff2') format('woff2'); +} +@font-face { + font-family: 'spacegrotesk'; + src: url('../fonts/space-grotesk-1.1.4/webfont/SpaceGrotesk-Regular.woff2') format('woff2'); +} + +@font-face { + font-family: 'space-mono'; + src: url('../fonts/space-mono/SpaceMono-Regular.ttf') format('truetype'); +} + +@font-face { + font-family: 'uncut-sans'; + src: url('../fonts/uncut-sans/Webfonts/UncutSans-Regular.woff2') format('woff2'); } /* General Styles */ body { - background-color: var(--secondary-color-bg); - color: var(--primary); - /*color: var(--primary);*/ + background-color: var(--color-background); + color: var(--color-accent-a); font-family: var(--font-family), monospace; font-weight: var(--font-weight); overflow-x: hidden; @@ -31,23 +54,59 @@ h1, p { main { position: relative; - z-index: 1; + z-index: 2; max-width: var(--page-max-width); margin: 0 auto; padding: 20px; - filter: drop-shadow(0 0 2px var(--secondary-color)) brightness(1); + /*filter: drop-shadow(0 0 2px var(--color-primary)) brightness(1);*/ } ::selection { - color: var(--bg-color); - background: var(--secondary-color); + color: var(--color-background); + background: var(--color-primary); } +/* 38c3 */ +.blobs { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: 1; /* Keep the container behind all content */ + pointer-events: none; /* Prevent interaction */ + overflow: hidden; +} + +.blobs img { + pointer-events: none; /* Ensure the images don't block anything */ + will-change: transform; /* Improve performance for animations */ +} + +.grid { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: -2; /* Ensure the grid is behind the blobs */ + display: grid; + pointer-events: none; /* Prevent interaction */ + opacity: 0.5; + background-image: linear-gradient(var(--color-accent-e) 1px, transparent 1px), + linear-gradient(90deg, var(--color-accent-e) 1px, transparent 1px); + background-size: 60px 60px; /* Adjust the grid spacing */ + background-color: var(--color-background); /* Base color for the grid */ +} + + /* Header Styles */ header { text-align: center; width: max-content; margin: 0 auto; + /*background-color: var(--color-background);*/ + /*border: 1px var(--color-accent-e) solid;*/ } header .names { @@ -57,7 +116,14 @@ header .names { header h1, header p { text-align: left; - color: var(--secondary-color); + font-size: 35px; + color: var(--color-primary); + font-family: pilowlava, monospace; +} + +header p { + font-family: space-mono, monospace; + font-size: 25px; } header img { @@ -66,10 +132,24 @@ header img { padding: 0; } +/* Description */ +header, .description, .linkGroup, .timer, footer { + background-color: rgba(15, 0, 10, 0.9); + /*border: 1px var(--color-primary) solid;*/ + border: 1px var(--color-accent-c) solid; +} + +header, .description, .linkGroup, .timer { + padding: 5px; +} + /* Links Styles */ h2 { width: 100%; + font-size: 30px; margin: 0; + color: var(--color-accent-a); + font-family: pilowlava, monospace; @media only screen and (max-width: 480px) { text-align: center; /* slim */ @@ -77,7 +157,7 @@ h2 { } @media only screen and (min-width: 480px) { - text-align: left; /* wide */ + text-align: center; /* wide */ margin: 0; } } @@ -91,7 +171,7 @@ h2 { } .text-link { - color: var(--secondary-color); + color: var(--color-primary); text-decoration: none; position: relative; padding: 5px; @@ -100,13 +180,13 @@ h2 { } .text-link:hover { - filter: drop-shadow(0 0 5px var(--secondary-color2)) brightness(1.02); + filter: drop-shadow(0 0 5px var(--color-primary)) brightness(1.02); top: -2px; } /* Links Container */ .links { - padding: 0 10px; + padding: 0 0; } /* Link Group */ @@ -119,6 +199,11 @@ h2 { } } +.linkGroup * { + color: var(--color-accent-a); + border: none; +} + /* Link Styles */ .link { height: fit-content; @@ -142,8 +227,8 @@ h2 { text-align: center; text-decoration: none; text-transform: lowercase; - color: var(--bg-color); - background-color: var(--secondary-color); + color: var(--color-background); + background-color: var(--color-primary); display: block; box-sizing: border-box; padding: 10px 20px; @@ -152,6 +237,7 @@ h2 { @media only screen and (min-width: 480px) { width: auto; /* wide */ + padding: 5px 20px; } } @@ -166,7 +252,7 @@ h2 { /* Default Hover Effect */ .hoverHighlight:hover { @media only screen and (min-width: 480px) { - filter: drop-shadow(0 0 8px var(--secondary-color)) brightness(1.1); + filter: drop-shadow(0 0 8px var(--color-primary)) brightness(1.1); top: -2px; } } @@ -178,7 +264,7 @@ h2 { /* Search Highlighting */ .highlightSearch { - filter: drop-shadow(0 0 8px var(--secondary-color)) brightness(1.1); + filter: drop-shadow(0 0 8px var(--color-primary)) brightness(1.1); z-index: 1; @media only screen and (min-width: 480px) { top: -2px; @@ -206,9 +292,9 @@ h2 { } #link-search { - background-color: var(--secondary-color2); - color: var(--secondary-color); - border: 2px solid var(--secondary-color2); + background-color: var(--color-background); + color: var(--color-accent-a); + border: 2px solid var(--color-primary); border-radius: 50px; padding: 10px 15px; font-size: 16px; @@ -221,21 +307,21 @@ h2 { } #link-search::placeholder { - color: var(--secondary-color); + color: var(--color-accent-a); opacity: 0.9; /* Placeholder text opacity */ } #link-search:focus::placeholder { - color: var(--secondary-color); + color: var(--color-accent-e); opacity: 0.9; /* Placeholder text opacity */ } #link-search:focus { outline: none; - background-color: var(--secondary-color-bg); - box-shadow: 0 0 10px var(--secondary-color); - border-color: var(--secondary-color2); - color: var(--secondary-color); + background-color: var(--color-background); + box-shadow: 0 0 10px var(--color-primary); + border-color: var(--color-primary); + color: var(--color-primary); } @media only screen and (max-width: 480px) { @@ -252,6 +338,9 @@ h2 { } /* Timers Styles */ +.timer { +} + .timer p { @media only screen and (max-width: 480px) { margin-bottom: 20px; /* slim */ @@ -259,7 +348,8 @@ h2 { } .timer p span { - color: var(--secondary-color); + color: var(--color-primary); + /*color: var(--color-primary);*/ text-decoration: none; } diff --git a/src/index.html b/src/index.html index 9fe2c1b..45cef41 100644 --- a/src/index.html +++ b/src/index.html @@ -6,10 +6,11 @@ Julian Brammer - + +
diff --git a/src/js/background.js b/src/js/background.js new file mode 100644 index 0000000..e1cbd01 --- /dev/null +++ b/src/js/background.js @@ -0,0 +1,105 @@ +function getRandomInt(min, max) { + return Math.floor(Math.random() * (max - min + 1)) + min; +} + +function generateGridPositions(rows, cols) { + const positions = []; + for (let row = 0; row < rows; row++) { + for (let col = 0; col < cols; col++) { + const top = (row + 0.5) * (100 / rows); + const left = (col + 0.5) * (100 / cols); + positions.push({ top, left }); + } + } + return positions; +} + +function getRandomPosition(availablePositions) { + const index = Math.floor(Math.random() * availablePositions.length); + return availablePositions.splice(index, 1)[0]; +} + +function createBlob(blobContainer, type, fileName, zIndex, position) { + const blob = document.createElement('img'); + blob.src = `assets/blobs/${fileName}`; + blob.classList.add(type); + + const randomRotation = getRandomInt(0, 360); + + // blob.style.top = `${Math.random() * 100}%`; + // blob.style.left = `${Math.random() * 100}%`; + blob.style.top = `${position.top}%`; + blob.style.left = `${position.left}%`; + blob.style.transform = `translate(-50%, -50%) rotate(${randomRotation}deg)`; + blob.style.position = 'absolute'; + blob.style.maxWidth = '300%'; + blob.style.opacity = type === 'line' ? '0.5' : '0.8'; + blob.style.zIndex = zIndex; + + blob.dataset.rotation = randomRotation; + blobContainer.appendChild(blob); + return blob; +} + +function adjustBlobCount() { + const width = window.innerWidth; + const height = window.innerHeight; + const baseCount = 5; + const widthFactor = Math.max(1, Math.floor(width / 400)); + const heightFactor = Math.max(1, Math.floor(height / 600)); + const totalCount = Math.min(baseCount * widthFactor, baseCount * heightFactor); + + const solidsCount = Math.max(1, Math.floor(totalCount * 0.5)); + const linesCount = totalCount - solidsCount; + + return { solidsCount, linesCount }; +} + + + + +document.addEventListener('DOMContentLoaded', () => { + const grid = document.createElement('div'); + grid.classList.add('grid'); + document.body.prepend(grid); + + const blobContainer = document.createElement('div'); + blobContainer.classList.add('blobs'); + document.body.prepend(blobContainer); + + const { solidsCount, linesCount } = adjustBlobCount(); + let zIndexCounter = 1; + + const gridSize = Math.ceil(Math.sqrt(solidsCount + linesCount)); + const positions = generateGridPositions(gridSize, gridSize); + + for (let i = 0; i < solidsCount; i++) { + const x = getRandomInt(1, 13); + const position = getRandomPosition(positions); + createBlob(blobContainer,'solid', `blob-freeform-${x}_filled.svg`, zIndexCounter, position); + zIndexCounter += 2; + } + + for (let i = 0; i < linesCount; i++) { + const x = getRandomInt(1, 13); + const position = getRandomPosition(positions); + const color = Math.random() > 0.5 ? '_red' : ''; + createBlob(blobContainer, 'line', `blob-freeform-${x}${color}.svg`, zIndexCounter - 1, position); + } +}); + + +document.addEventListener('mousemove', (event) => { + const elements = [...document.querySelectorAll('.solid, .line')]; + const { clientX: mouseX, clientY: mouseY } = event; + const { innerWidth: width, innerHeight: height } = window; + + const xOffset = (mouseX / width - 0.5) * 200; + const yOffset = (mouseY / height - 0.5) * 200; + + elements.forEach((element, i) => { + const strength = element.classList.contains('solid') ? 5 + i * 3 : 1 + i * 0.5; + const rotation = element.dataset.rotation || 0; + element.style.transform = `translate(-50%, -50%) translate(${xOffset / strength}px, ${yOffset / strength}px) rotate(${rotation}deg)`; + }); +}); \ No newline at end of file diff --git a/src/js/blobs.js b/src/js/blobs.js new file mode 100644 index 0000000..87c71ac --- /dev/null +++ b/src/js/blobs.js @@ -0,0 +1,103 @@ +document.addEventListener('DOMContentLoaded', () => { + // Add the grid element to the body + const grid = document.createElement('div'); + grid.classList.add('grid'); + document.body.prepend(grid); // Add grid to the very back + + const container = document.createElement('div'); + container.classList.add('blobs'); // Use "blobs" as the container class + document.body.prepend(container); + + // Function to get a weighted random value favoring edges + const getEdgeBiasedRandom = () => { + const rand = Math.random(); // Random number between 0 and 1 + if (rand < 0.5) { + // Favor edges (closer to 10% or 90%) + return Math.random() < 0.5 ? getRandomInt(5, 25) : getRandomInt(75, 95); + } else { + // Occasionally place blobs elsewhere (30-70%) + return getRandomInt(25, 75); + } + }; + + // Function to get a random integer between min and max (inclusive) + const getRandomInt = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min; + + // Function to adjust the number of blobs based on window size + const adjustBlobCount = () => { + const width = window.innerWidth; + const height = window.innerHeight; + + // Base number of blobs, and scale based on window width and height + const baseCount = 5; + const widthMultiplier = Math.max(1, Math.floor(width / 500)); // Increase blobs per 500px width + const heightMultiplier = Math.max(1, Math.floor(height / 500)); // Increase blobs per 400px height + + const totalCount = Math.min(baseCount * widthMultiplier, baseCount * heightMultiplier); + + // Return number of solids and lines based on adjusted total count + const NUM_SOLIDS = Math.max(1, Math.floor(totalCount * 0.3)); // 30% solids + const NUM_LINES = totalCount - NUM_SOLIDS; // The rest are lines + + return { NUM_SOLIDS, NUM_LINES }; + }; + + // Get the number of blobs based on the window size + const { NUM_SOLIDS, NUM_LINES } = adjustBlobCount(); + + // Create and position blobs with distinct z-index layers + let zIndexCounter = 1; // Start z-index at 1 to avoid overlap with default content + + // Randomly select and create solids (background blobs) + for (let i = 0; i < NUM_SOLIDS; i++) { + const x = getRandomInt(1, 13); // Randomly pick a blob design + createBlob('background-blob', `blob-freeform-${x}_filled.svg`, zIndexCounter); + zIndexCounter += 2; // Increment by 2 to leave gaps for lines + } + + // Randomly select and create lines (foreground blobs) + for (let i = 0; i < NUM_LINES; i++) { + const x = getRandomInt(1, 13); // Randomly pick a blob design + const color = Math.random() > 0.5 ? '_red' : ''; // 50% chance to pick the red variant + createBlob('background-line', `blob-freeform-${x}${color}.svg`, zIndexCounter - 1); // Ensure lines fit between solids + } + + // Function to create and position a blob + function createBlob(type, fileName, zIndex) { + const blob = document.createElement('img'); + blob.src = `assets/blobs/${fileName}`; // Corrected path to assets folder + blob.classList.add(type); + blob.style.top = `${getEdgeBiasedRandom()}%`; // Use edge-biased random for top + blob.style.left = `${getEdgeBiasedRandom()}%`; // Use edge-biased random for left + blob.style.transform = `translate(-50%, -50%)`; + blob.style.position = 'absolute'; + blob.style.maxWidth = '300%'; // Adjust size + blob.style.opacity = type === 'background-line' ? '0.5' : '0.8'; // More transparent for lines + blob.style.zIndex = zIndex; // Set z-index dynamically + container.appendChild(blob); + return blob; + } + + // Add mouse movement effect + document.addEventListener('mousemove', (event) => { + const blobs = document.querySelectorAll('.background-blob'); + const lines = document.querySelectorAll('.background-line'); + + const { clientX: mouseX, clientY: mouseY } = event; + const { innerWidth: width, innerHeight: height } = window; + + // Stronger movement scaling factors + const xOffset = (mouseX / width - 0.5) * 100; // Amplified to 100 for stronger movements + const yOffset = (mouseY / height - 0.5) * 100; + + blobs.forEach((blob, i) => { + const strength = 3 + i; // Reduce divisor for stronger movements + blob.style.transform = `translate(-50%, -50%) translate(${xOffset / strength}px, ${yOffset / strength}px)`; + }); + + lines.forEach((line, i) => { + const strength = 2 + i * 0.5; // Even stronger for lines + line.style.transform = `translate(-50%, -50%) translate(${xOffset / strength}px, ${yOffset / strength}px)`; + }); + }); +});