diff --git a/index.html b/index.html index 314d3b1..d57bf9b 100644 --- a/index.html +++ b/index.html @@ -1,162 +1,37 @@ - - - - - - - - Site title - - - - - - - + + + + + John Doe - Portfolio Moderne + + + - - - - - -
-

- Site title -

- -
- -
- -
- -

This is the homepage, displayed by default.

- -
- -
- -

This is the about page. This is a link to another page.

- -
- - - -
Example of an image with a link to a larger version.
-
- -
- -
- -
-

Blogging with Joe Bloggs

-

One could use this setup to write a blog short updates. For images make sure to use the loading="lazy" attribute, so they get loaded only when needed. - - You might be able to use it for iframe embeds too(?), but maybe just write a link to the Youtube video instead. - -

-
- - - -
- -
- -

An example of a photo gallery with a lightbox.

+ + - - -
- - - - - - - - - - - - - - - -
- -
- -
+
-
-
-
-
-
-

You could also have text over here…

-
-
- -
…or image captions
-
-
- -
add a solid background
-
-
- -

or go full bleed

-
-
+
+ +
-
- -
- -

This page is not referenced in the menu, yet it exists.

-

← back

- -
- -
- - +
- - - - - - - - - - - - - - - - - + + + + + - - - - - + + + \ No newline at end of file diff --git a/main.js b/main.js new file mode 100644 index 0000000..a51ac85 --- /dev/null +++ b/main.js @@ -0,0 +1,109 @@ +$(document).ready(function() { + // --- SCÈNE 3D AVEC THREE.JS --- + let scene, camera, renderer, cube; + + function initThree() { + const container = $('#canvas-container')[0]; + scene = new THREE.Scene(); + camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); + renderer = new THREE.WebGLRenderer({ alpha: true }); + renderer.setSize(window.innerWidth, window.innerHeight); + container.appendChild(renderer.domElement); + + const geometry = new THREE.BoxGeometry(1.5, 1.5, 1.5); + const material = new THREE.MeshNormalMaterial(); + cube = new THREE.Mesh(geometry, material); + scene.add(cube); + + camera.position.z = 5; + + animate(); + } + + function animate() { + requestAnimationFrame(animate); + cube.rotation.x += 0.005; + cube.rotation.y += 0.005; + renderer.render(scene, camera); + } + + $(window).on('resize', () => { + renderer.setSize(window.innerWidth, window.innerHeight); + camera.aspect = window.innerWidth / window.innerHeight; + camera.updateProjectionMatrix(); + }); + + // --- GESTION DE LA NAVIGATION (ROUTING CÔTÉ CLIENT) --- + const routes = { + '#home': ` +
+

Bienvenue

+

Un portfolio interactif construit avec les dernières technologies du web.

+
`, + '#about': ` +
+

À propos de moi

+

Je suis un développeur passionné par le design créatif et les expériences utilisateur immersives. Ce site est une démonstration de ce qu'il est possible de faire avec des outils comme Three.js et GSAP.

+
`, + '#portfolio': ` +
+

Portfolio

+
+ ${Array.from({length: 6}, (_, i) => ` +
+
+ Projet ${i + 1} +
+
Projet ${i + 1}
+
+
+
+ `).join('')} +
+
`, + '#news': ` +
+

Actualités

+

Les dernières nouvelles et mises à jour seront publiées ici.

+
` + }; + + function loadContent(hash) { + const content = routes[hash] || routes['#home']; + const $mainContent = $('#main-content'); + + // Animation de sortie avec GSAP + gsap.to($mainContent, { + opacity: 0, + y: 20, + duration: 0.4, + onComplete: () => { + $mainContent.html(content); + // Animation d'entrée + gsap.fromTo($mainContent, { opacity: 0, y: -20 }, { opacity: 1, y: 0, duration: 0.5 }); + } + }); + + // Visibilité de la scène 3D + if (hash === '#home' || !hash) { + gsap.to('#canvas-container', { opacity: 1, duration: 1 }); + } else { + gsap.to('#canvas-container', { opacity: 0, duration: 1 }); + } + } + + // Gestion des clics sur les liens de navigation + $('.nav-link').on('click', function(e) { + e.preventDefault(); + const hash = $(this).attr('href'); + window.location.hash = hash; + }); + + // Gérer le changement de hash (navigation via les boutons précédent/suivant du navigateur) + $(window).on('hashchange', function() { + loadContent(window.location.hash); + }).trigger('hashchange'); // Charge le contenu initial + + // Initialiser la scène 3D + initThree(); +}); \ No newline at end of file diff --git a/style.css b/style.css index 48a7d14..9d9e1b0 100644 --- a/style.css +++ b/style.css @@ -1,479 +1,58 @@ -* { margin: 0; padding: 0; box-sizing: border-box; - - /* Color scheme */ - - --textcolor: #121212; - --bgcolor: #fff; - --highlight: #2749c9; - +:root { + --bg-color: #ffffff; + --text-color: #212529; + --link-color: #0d6efd; + --link-hover-color: #0a58ca; } -@media (prefers-color-scheme: dark) { - * { - --textcolor: #dadada; - --bgcolor: #141414; - --highlight: #ffc400; - } +[data-theme="dark"] { + --bg-color: #212529; + --text-color: #f8f9fa; + --link-color: #0dcaf0; + --link-hover-color: #3dd5f3; } body { - font-size: 18px; - font-family: system-ui, sans-serif; - line-height: 1.4; - color: var(--textcolor); - background: var(--bgcolor); - position: relative; - max-width: 64em; /* remove this for a full-width layout */ - margin: 0 auto; /* centers the layout */ + background-color: var(--bg-color); + color: var(--text-color); + transition: background-color 0.3s, color 0.3s; + overflow-x: hidden; /* Empêche le défilement horizontal */ } -/* ------- Sections ------- */ - -section { - padding: calc(6em + 5vw) 5vw 8vw 5vw; - /* ! Everything below is needed ! */ - display: none; - position: absolute; - top: 0; - min-height: 100vh; - width: 100%; - background: var(--bgcolor); +#canvas-container { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: -1; } -section:target { /* Show section */ - display: block; -} - -section#home { /* Show #home by default */ - display: block; -} - -/* ------- Header ------- */ - header { - padding: 5vw 5vw 0 5vw; - display: flex; - flex-wrap: wrap; - position: absolute; - width: 100%; - z-index: 2; -} - -header h1 { - font-size: 1em; - flex: 1; /* pushes nav to the right */ - white-space: nowrap; - padding: 0 5vw .5em 0; -} - -nav a:not(:last-of-type) { - margin-right: 1.5vw; -} - -/* ------- General ------- */ - -a { - text-decoration: none; - color: var(--highlight); -} - -a:hover { - border-bottom: 1px solid; -} - -section h1 { - font-size: 1em; - margin: 0 0 1em 0; -} - -h2, h3, h4 { - font-size: 1em; - font-weight: 600; - margin: 1.6em 0 .6em 0; -} - -p, ul, ol, article { - max-width: 60ch; /* Limit line-length to 60 characters */ - margin-bottom: .6em; -} - -ul { - list-style-type: none; -} - -ul li::marker { - content: "\2022 "; -} - -li { - margin-bottom: .2em; -} - -ul, ol { - padding-left: 2ch; -} - -b, strong { - font-weight: 600; -} - -small { - font-size: .85em; -} - -hr { - height: 1px; - border: 0; - background: currentColor; - opacity: .1; - margin: 1.2em 0; -} - -abbr { - text-decoration: none; -} - -abbr[title]:hover { - opacity: .7; - cursor: help; -} - -blockquote { - padding-left: 2ch; - opacity: .7; - margin-bottom: .6em; - position: relative; + z-index: 10; } -blockquote:before { - content: ""; - position:absolute; - left: 0; - top: .3em; - bottom: .3em; - background: currentColor; - width: 1px; - opacity: .2; +.nav-link { + color: var(--text-color); + font-weight: 500; } -img, svg, video, audio { - display: block; - max-width: 100%; - height: auto; - fill: currentColor; -} - -code, textarea { - font-family: ui-monospace, SF Mono, Menlo, Monaco, Andale Mono, monospace; - font-size: 1em; - opacity: .7; -} - -a code { - opacity:1; -} - -pre, textarea { /* for code samples */ - font-size: .9em; - color: inherit; - line-height:inherit; - padding:.6em .9em; - margin: .8em 0 1em 0; - position: relative; - display: block; - width: 100%; - white-space: pre; - border:0; - border-radius: 4px; - background:rgba(255,255,100,.075); - box-shadow: inset 1px 1px 0 rgba(0,0,0,.2), inset -1px -1px 0 rgba(0,0,0,.04) ; -} - -/* Inline footnotes */ - -label { - cursor: pointer; - vertical-align: super; - line-height: 1; - font-size: .75em; - padding-left: .1em; +.nav-link.active, +.nav-link:hover { + color: var(--link-hover-color); } -label:hover { - color: var(--highlight); -} - -label:before {content:"[";} -label:after {content:"]";} - -label + input, -label + input + small { - display: none; -} - -input:checked + small { - display: block; - padding: .8em 0 1em 2.5vw;; -} - -/* Figures */ - -figure { - margin: 2em 0 1.5em 0; -} - -figure figcaption { - margin: 0.8em 0 0 0; - font-size: .85em; - opacity: .7; -} - -/* Responsive video embeds */ - -figure.video { - position: relative; - padding-bottom: 56.25%; /* 16:9 */ - height: 0; - overflow: hidden; -} - -figure.video iframe, figure.video object, figure.video embed { - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - border: 0; - visibility: hidden; /* so loading="lazy" should work? */ -} - -section:target iframe { - visibility: visible; -} - -/* External links */ - -a[href*="//"]:after { - font-weight: 300; - font-size: .85em; - content: "\2197"; /* top right arrow: ↗ */ - color: var(--textcolor); - opacity: .25; -} - -a[href*="//"]:hover:after { - color: var(--highlight); - opacity: 1; -} - -/* File links */ - -a:before { - font-size: .7em; - margin-right: .4em; -} - -/* Add more filetypes here if you want */ - -a[href$=".pdf"]:before { content: "PDF"; } -a[href$=".txt"]:before { content: "TXT"; } -a[href$=".mp3"]:before { content: "MP3"; } -a[href$=".zip"]:before { content: "ZIP"; } -a[href$=".rar"]:before { content: "RAR"; } -a[href$=".jpeg"]:before, -a[href$=".jpg"]:before, -a[href$=".gif"]:before, -a[href$=".png"]:before { content: "IMG"; } - -/* ------- News ------- */ - -article + article { - margin-top: 4.5em; -} - -article h2 { - font-weight: 700; - margin: 0 0 1em 0; -} - -article time { - margin-left: .6em; - font-size: .8em; - font-weight: 400; - opacity: .7; -} - -/* ------- Images Grid ------- */ - -.grid { - display: grid; - grid-gap: 5vmin; - grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); /* 150px = minimum image size */ - grid-auto-flow: dense; - padding: 2em 0; -} - -.grid a { - position: relative; - border: 0; -} - -.grid a:hover { - transform: scale(.975); -} - -/* For a square ratio */ -.grid a:before { - content: ""; - display: block; - padding-top: 100%; -} - -.grid a img { - position: absolute; - top: 0; - width: 100%; - height: 100%; - object-fit: contain; -} - -/* ------- Slideshow ------- */ - -.slides { - position: fixed; - top: 0; - left: 0; - right: 0; - height: 100vh; - overflow-y: scroll; - scroll-snap-type: y mandatory; -} - -.slides figure { - height: 100vh; - padding: 0 5vw; - margin: 0; - display: grid; - place-items: center; - align-content: center; - scroll-snap-align: center; -} - -.slides figure img { - max-height: 88vh; /* Adjust if needed */ -} - -.slides figure.cover { - padding: 0; -} - -.slides figure.cover img { - max-height: none; - position: absolute; - z-index: -1; - width: 100vw; - height: 100vh; - object-fit: cover; -} - -/* ------- Lightbox ------- */ - -.lightbox { - display: none; - color: var(--textcolor); -} - -.lightbox:target { - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; - display: grid; - place-items: center; - align-content: center; - background: var(--bgcolor); - border: 0; - z-index: 3; -} - -.lightbox img { - max-height: 100vh; - z-index: 4; -} - -.lightbox:target:before { /* Loading spinner */ - content:""; - height: 2em; - width: 2em; - animation: spin .8s infinite linear; - border: 1px solid; - border-right-color: transparent; - border-radius: 50%; - display: block; - position: absolute; - transform: translateX(-50%); - opacity: .25; -} - -@keyframes spin { - 0% { transform: rotate(0deg); } - 100% { transform: rotate(360deg); } -} - -.lightbox:target:after { /* × to close */ - content: "\00D7"; - position: fixed; - font-size: 2em; - font-weight: 200; - line-height: 0; - top: .75em; - right: .5em; - z-index: 4; -} - -/* ------- Smaller screens ------- */ - -@media only screen and (max-width: 680px) { - body { font-size: 16px; } -} - -@media only screen and (max-width: 540px) { - nav { width: 100%; } /* Fix for older webkit versions */ -} - -/* ------- Print ------- */ - -@media print { - - nav, .lightbox:target:after { display: none; } - - article, figure, img { - page-break-inside: avoid; - break-inside: avoid; - } - - /* Inline footnotes */ - - label + input + small { display: inline; } - label + input + small:before { content: "["; } - label + input + small:after { content: "]"; } - - /* Slides */ - - .slides, .slides figure { - position: relative; - height: auto; - padding: 0; - } - - .slides figure img, .slides figure.cover img { - max-height: auto; +main { + padding-top: 80px; + padding-bottom: 40px; position: relative; z-index: 1; - width: auto; - height: 100vh; - object-fit: contain; - } - +} + +.page-content { + background-color: rgba(var(--bg-color), 0.8); + backdrop-filter: blur(10px); + -webkit-backdrop-filter: blur(10px); + padding: 2rem; + border-radius: 15px; } \ No newline at end of file