add 38c3 theming
This commit is contained in:
parent
03c801ecc5
commit
13f6399fc0
@ -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"
|
||||
},
|
||||
{
|
||||
|
154
src/css/main.css
154
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;
|
||||
}
|
||||
|
||||
|
@ -6,10 +6,11 @@
|
||||
<title>Julian Brammer</title>
|
||||
<link rel="stylesheet" href="css/main.css">
|
||||
<link rel="me" href="https://social.brulijam.com/@brulijam">
|
||||
<script src="js/main.js"></script>
|
||||
<!-- <script src="js/main.js"></script>-->
|
||||
<script src="js/fuzzysearch.js" type="module"></script>
|
||||
<script src="js/links.js"></script>
|
||||
<script src="js/timer.js"></script>
|
||||
<script src="js/background.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<main>
|
||||
|
105
src/js/background.js
Normal file
105
src/js/background.js
Normal file
@ -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)`;
|
||||
});
|
||||
});
|
103
src/js/blobs.js
Normal file
103
src/js/blobs.js
Normal file
@ -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)`;
|
||||
});
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue
Block a user