portfolio : galerie horizontale 3 rangées + mockup conditionnel
All checks were successful
Deploy / Deploy to Production (push) Successful in 25s

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
isUnknown 2026-03-24 18:53:27 +01:00
parent 133651c35d
commit cb51e050e4
2 changed files with 42 additions and 32 deletions

View file

@ -2,7 +2,7 @@
/**
* GalleryAnimation — animation CSS de galerie défilante.
* Mode vertical : 3 colonnes (haut/bas)
* Mode horizontal : 5 rangées (gauche/droite)
* Mode horizontal : 3 rangées (gauche/droite)
* @prop {Array<{src: string, srcset: string, webp: string}>} images
* @prop {number} secondsPerImage — durée par image (défaut: 8s)
* @prop {'vertical'|'horizontal'} mode — direction du défilement
@ -16,10 +16,8 @@
const defs = mode === 'horizontal'
? [
{ offset: 0, delay: 0 },
{ offset: Math.floor(count / 5), delay: duration / 5 },
{ offset: Math.floor(2 * count / 5), delay: 2 * duration / 5 },
{ offset: Math.floor(count / 5), delay: 3 * duration / 5 },
{ offset: 0, delay: 4 * duration / 5 },
{ offset: Math.floor(count / 3), delay: duration / 3 },
{ offset: 0, delay: 2 * duration / 3 },
]
: [
{ offset: 0, delay: 0 },
@ -92,7 +90,7 @@
opacity: .5;
}
:global(.gallery-animation__image) {
.gallery-animation__image {
display: block;
object-fit: contain;
}
@ -108,14 +106,14 @@
transform: scale(1.2);
}
.gallery-animation--vertical :global(.gallery-animation__column) {
.gallery-animation--vertical .gallery-animation__column {
flex: 1;
display: flex;
flex-direction: column;
overflow: hidden;
}
.gallery-animation--vertical :global(.gallery-animation__track) {
.gallery-animation--vertical .gallery-animation__track {
display: flex;
flex-direction: column;
row-gap: 1rem;
@ -123,17 +121,17 @@
animation-iteration-count: infinite;
}
.gallery-animation--vertical :global(.gallery-animation__column:nth-child(odd) .gallery-animation__track) {
.gallery-animation--vertical .gallery-animation__column:nth-child(odd) .gallery-animation__track {
animation-name: galleryScrollDown;
animation-duration: var(--gallery-duration);
}
.gallery-animation--vertical :global(.gallery-animation__column:nth-child(even) .gallery-animation__track) {
.gallery-animation--vertical .gallery-animation__column:nth-child(even) .gallery-animation__track {
animation-name: galleryScrollUp;
animation-duration: var(--gallery-duration);
}
.gallery-animation--vertical :global(.gallery-animation__image) {
.gallery-animation--vertical .gallery-animation__image {
width: 100%;
height: auto;
}
@ -149,48 +147,48 @@
}
/* ==========================================================================
MODE HORIZONTAL — 5 rangées
MODE HORIZONTAL — 3 rangées
========================================================================== */
.gallery-animation--horizontal {
display: flex;
flex-direction: column;
transform: scale(1.2);
justify-content: space-evenly;
}
.gallery-animation--horizontal :global(.gallery-animation__column) {
--inner-height: 100vh;
height: clamp(calc(var(--inner-height) / 5), 20%, calc(var(--inner-height) / 3));
.gallery-animation--horizontal .gallery-animation__column {
display: flex;
flex-direction: row;
align-items: stretch;
overflow: hidden;
}
.gallery-animation--horizontal :global(.gallery-animation__track) {
.gallery-animation--horizontal .gallery-animation__track {
display: flex;
flex-direction: row;
align-items: stretch;
height: 100%;
column-gap: 1rem;
column-gap: 1.8vh;
animation-timing-function: linear;
animation-iteration-count: infinite;
}
.gallery-animation--horizontal :global(.gallery-animation__column:nth-child(odd) .gallery-animation__track) {
.gallery-animation--horizontal .gallery-animation__column:nth-child(odd) .gallery-animation__track {
animation-name: galleryScrollRight;
animation-duration: var(--gallery-duration);
}
.gallery-animation--horizontal :global(.gallery-animation__column:nth-child(even) .gallery-animation__track) {
.gallery-animation--horizontal .gallery-animation__column:nth-child(even) .gallery-animation__track {
animation-name: galleryScrollLeft;
animation-duration: var(--gallery-duration);
}
.gallery-animation--horizontal :global(.gallery-animation__image) {
height: 100%;
width: auto;
flex-shrink: 0;
.gallery-animation--horizontal picture {
width: 56vh;
}
.gallery-animation--horizontal .gallery-animation__image {
width: 100%;
border-radius: 2vh;
overflow: hidden;
}
@keyframes galleryScrollRight {
@ -208,7 +206,7 @@
========================================================================== */
@media (prefers-reduced-motion: reduce) {
:global(.gallery-animation__track) {
.gallery-animation__track {
animation: none;
}
}

View file

@ -103,7 +103,7 @@
</div>
<!-- Mockup device (centre) -->
<div class="portfolio-mockup">
<div class="portfolio-mockup portfolio-mockup--{currentProject.galleryAnimationMode}">
<ResponsivePicture
src={currentProject.mockup}
srcset={currentProject.mockupSrcset}
@ -195,13 +195,21 @@
}
.portfolio-mockup {
grid-area: 6/7 / span 10 / span 4;
grid-area: 6/7 / span 10 / span 5;
z-index: var(--z-content);
display: flex;
align-items: center;
justify-content: center;
}
.portfolio-mockup--horizontal {
grid-area: 6/1 / span 10 / span 7;
}
.portfolio-mockup--horizontal :global(picture) {
transform: scale(1.25);
}
.portfolio-mockup :global(picture),
.portfolio-mockup :global(.portfolio-mockup-img) {
width: 100%;
@ -397,13 +405,17 @@
z-index: var(--z-content);
}
.portfolio-mockup--vertical {
transform: scale(.8);
}
.portfolio-mockup :global(.portfolio-mockup-img) {
height: auto;
}
/* Text — over mockup, centered */
.portfolio-text {
grid-area: 9/4/span 8/span 14;
grid-area: 10/4/span 8/span 14;
z-index: var(--z-content);
gap: .5rem;
text-align: center;
@ -464,8 +476,8 @@
}
.portfolio-nav-item img {
width: 3.75rem;
height: 3.75rem;
width: 3rem;
height: 3rem;
}
.portfolio-nav-number {