divide report in subsection
All checks were successful
Deploy / Deploy to Production (push) Successful in 12s
All checks were successful
Deploy / Deploy to Production (push) Successful in 12s
This commit is contained in:
parent
4262be067d
commit
ecd379dee4
5 changed files with 396 additions and 579 deletions
|
|
@ -2910,66 +2910,12 @@ main .page__header .description-medium {
|
|||
left: 0px;
|
||||
}
|
||||
}
|
||||
.arrow-report {
|
||||
font-size: 14px;
|
||||
color: var(--color-txt-light);
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
.media-anchor {
|
||||
width: 100%;
|
||||
height: 0px;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
.media-anchor .arrow-report {
|
||||
position: relative;
|
||||
left: 50px;
|
||||
top: 8px;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 768px) {
|
||||
[data-template=report] .report__header {
|
||||
margin-inline: auto;
|
||||
max-width: var(--max-w-cards);
|
||||
margin-top: calc(var(--spacing) * 3);
|
||||
margin-bottom: calc(var(--spacing) * 4);
|
||||
}
|
||||
[data-template=report] .report__content {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
grid-gap: calc(var(--padding-body) * 2.5);
|
||||
z-index: calc(var(--z-header) - 100);
|
||||
}
|
||||
[data-template=report] .report__content .report__txt {
|
||||
grid-row: 1;
|
||||
grid-column: 1;
|
||||
max-width: var(--max-w-content);
|
||||
}
|
||||
[data-template=report] .report__content #report__medias {
|
||||
z-index: calc(var(--z-header) - 100);
|
||||
position: sticky;
|
||||
top: calc(var(--header-h) + var(--padding-body));
|
||||
align-self: start;
|
||||
grid-row: 1;
|
||||
grid-column: 2;
|
||||
min-height: 100px;
|
||||
}
|
||||
[data-template=report] .report__content #arrow__medias {
|
||||
z-index: calc(var(--z-header) - 100);
|
||||
position: sticky;
|
||||
top: calc(var(--header-h) + var(--padding-body));
|
||||
align-self: start;
|
||||
grid-row: 1;
|
||||
grid-column: 2;
|
||||
transform: rotate(180deg);
|
||||
transform-origin: center;
|
||||
}
|
||||
[data-template=report] .report__content #arrow__medias span {
|
||||
position: relative;
|
||||
left: 26px;
|
||||
top: calc(var(--spacing) * -5);
|
||||
margin-top: calc(var(--spacing) * 3.25);
|
||||
margin-bottom: calc(var(--spacing) * 4);
|
||||
}
|
||||
[data-template=report] #toggle-panel {
|
||||
position: fixed;
|
||||
|
|
@ -3000,7 +2946,6 @@ main .page__header .description-medium {
|
|||
transition: left ease-in-out 0.5s;
|
||||
}
|
||||
[data-template=report] #report {
|
||||
padding-left: calc(var(--padding-body) * 2);
|
||||
transition: padding-left ease-in-out 0.5s;
|
||||
}
|
||||
[data-template=report] .panel-open #report__aside {
|
||||
|
|
@ -3026,16 +2971,16 @@ main .page__header .description-medium {
|
|||
.report__header .report__title-group .title {
|
||||
text-transform: uppercase;
|
||||
font-weight: normal;
|
||||
font-size: var(--fs-big);
|
||||
font-size: var(--fs-medium);
|
||||
line-height: var(--leading-tight);
|
||||
font-weight: normal;
|
||||
font-weight: 500;
|
||||
margin-top: calc(var(--spacing) * 1);
|
||||
text-wrap: balance;
|
||||
}
|
||||
.report__header .report__title-group .subtitle {
|
||||
font-size: var(--fs-big);
|
||||
font-size: var(--fs-medium);
|
||||
line-height: var(--leading-tight);
|
||||
font-weight: normal;
|
||||
font-weight: 500;
|
||||
text-wrap: balance;
|
||||
}
|
||||
.report__header figure {
|
||||
|
|
@ -3058,6 +3003,7 @@ main .page__header .description-medium {
|
|||
grid-row: 2;
|
||||
grid-column: 1;
|
||||
align-self: end;
|
||||
font-size: var(--fs-small);
|
||||
border-bottom: var(--border-light);
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
|
@ -3085,7 +3031,9 @@ main .page__header .description-medium {
|
|||
}
|
||||
|
||||
.report__content .section-content {
|
||||
padding-bottom: calc(var(--spacing) * 3);
|
||||
padding-left: calc(var(--padding-body) * 1.5);
|
||||
padding-right: calc(var(--padding-body) * 1.5);
|
||||
margin-bottom: calc(var(--spacing) * 4);
|
||||
}
|
||||
.report__content .section-content:target {
|
||||
padding-top: calc(var(--header-h) + var(--spacing) * 2);
|
||||
|
|
@ -3096,12 +3044,39 @@ main .page__header .description-medium {
|
|||
}
|
||||
}
|
||||
.report__content .section-title {
|
||||
max-width: var(--max-w-content);
|
||||
margin-inline: auto;
|
||||
margin-bottom: calc(var(--spacing) * 2);
|
||||
font-size: var(--fs-medium);
|
||||
margin-bottom: var(--spacing);
|
||||
font-weight: normal;
|
||||
font-weight: 500;
|
||||
text-transform: uppercase;
|
||||
text-wrap: balance;
|
||||
max-width: 42ch;
|
||||
max-width: var(--max-w-content);
|
||||
color: var(--color-accent);
|
||||
}
|
||||
.report__content .section-txt {
|
||||
max-width: var(--max-w-content);
|
||||
margin-inline: auto;
|
||||
}
|
||||
.report__content .subsection-w-media {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: var(--padding-body);
|
||||
margin-bottom: calc(var(--spacing) * 3);
|
||||
position: relative;
|
||||
}
|
||||
.report__content .subsection-txt {
|
||||
max-width: var(--max-w-content);
|
||||
padding-left: var(--padding-inner);
|
||||
padding-right: var(--padding-inner);
|
||||
}
|
||||
.report__content .media {
|
||||
margin-inline: auto;
|
||||
max-width: var(--max-w-content);
|
||||
padding-left: var(--padding-inner);
|
||||
padding-right: var(--padding-inner);
|
||||
position: sticky;
|
||||
top: 0px;
|
||||
}
|
||||
.report__content p {
|
||||
margin: calc(var(--spacing) * 0.5) 0;
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -49,28 +49,6 @@
|
|||
}
|
||||
|
||||
|
||||
.arrow-report{
|
||||
font-size: 14px;
|
||||
color: var(--color-txt-light);
|
||||
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
|
||||
}
|
||||
|
||||
.media-anchor{
|
||||
width: 100%;
|
||||
height: 0px;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
|
||||
.arrow-report{
|
||||
position: relative;
|
||||
left: 50px;
|
||||
top: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@media #{$small-up}{
|
||||
|
|
@ -79,56 +57,19 @@
|
|||
|
||||
.report__header {
|
||||
margin-inline: auto;
|
||||
max-width: var(--max-w-cards);
|
||||
margin-top: calc(var(--spacing) * 3);
|
||||
max-width: var(--max-w-content);
|
||||
margin-top: calc(var(--spacing) * 3.25);
|
||||
margin-bottom: calc(var(--spacing) * 4);
|
||||
}
|
||||
|
||||
.report__content {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
grid-gap: calc(var(--padding-body)*2.5);
|
||||
z-index: calc(var(--z-header) - 100);
|
||||
|
||||
.report__txt {
|
||||
grid-row: 1;
|
||||
grid-column: 1;
|
||||
max-width: var(--max-w-content);
|
||||
}
|
||||
|
||||
#report__medias {
|
||||
z-index: calc(var(--z-header) - 100);
|
||||
position: sticky;
|
||||
top: calc(var(--header-h) + var(--padding-body));
|
||||
align-self: start;
|
||||
|
||||
// border-left: var(--border-light);
|
||||
// padding-left: var(--padding-inner);
|
||||
grid-row: 1;
|
||||
grid-column: 2;
|
||||
// border: var(--border-light);
|
||||
min-height: 100px;
|
||||
|
||||
}
|
||||
|
||||
#arrow__medias{
|
||||
z-index: calc(var(--z-header) - 100);
|
||||
position: sticky;
|
||||
top: calc(var(--header-h) + var(--padding-body));
|
||||
align-self: start;
|
||||
|
||||
|
||||
grid-row: 1;
|
||||
grid-column: 2;
|
||||
transform: rotate(180deg);
|
||||
transform-origin: center;
|
||||
|
||||
|
||||
span{
|
||||
position: relative;
|
||||
left: 26px;
|
||||
top: calc(var(--spacing)*-5);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -170,7 +111,7 @@
|
|||
transition: left ease-in-out .5s;
|
||||
}
|
||||
#report {
|
||||
padding-left: calc(var(--padding-body)*2);
|
||||
// padding-left: calc(var(--padding-body)*2);
|
||||
transition: padding-left ease-in-out .5s;
|
||||
}
|
||||
|
||||
|
|
@ -213,17 +154,17 @@
|
|||
.title {
|
||||
text-transform: uppercase;
|
||||
font-weight: normal;
|
||||
font-size: var(--fs-big);
|
||||
font-size: var(--fs-medium);
|
||||
line-height: var(--leading-tight);
|
||||
font-weight: normal;
|
||||
font-weight: 500;
|
||||
margin-top: calc(var(--spacing)*1);
|
||||
text-wrap: balance;
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
font-size: var(--fs-big);
|
||||
font-size: var(--fs-medium);
|
||||
line-height: var(--leading-tight);
|
||||
font-weight: normal;
|
||||
font-weight: 500;
|
||||
text-wrap: balance;
|
||||
|
||||
}
|
||||
|
|
@ -241,7 +182,7 @@
|
|||
grid-row: 2;
|
||||
grid-column: 1;
|
||||
align-self: end;
|
||||
// font-size: var(--fs-small);
|
||||
font-size: var(--fs-small);
|
||||
border-bottom: var(--border-light);
|
||||
align-items: flex-start;
|
||||
|
||||
|
|
@ -285,7 +226,10 @@
|
|||
|
||||
|
||||
.section-content {
|
||||
padding-bottom: calc(var(--spacing)*3);
|
||||
// min-height: calc(100vh - var(--header-h));
|
||||
padding-left: calc(var(--padding-body)*1.5);
|
||||
padding-right: calc(var(--padding-body)*1.5);
|
||||
margin-bottom: calc(var(--spacing)*4);
|
||||
&:target{
|
||||
padding-top: calc(var(--header-h) + var(--spacing)*2);
|
||||
@media #{$small}{ padding-top: calc(var(--header-h) + var(--spacing)*0.5); }
|
||||
|
|
@ -296,14 +240,52 @@
|
|||
|
||||
|
||||
.section-title {
|
||||
|
||||
max-width: var(--max-w-content);
|
||||
margin-inline: auto;
|
||||
margin-bottom: calc(var(--spacing)*2);
|
||||
|
||||
font-size: var(--fs-medium);
|
||||
margin-bottom: var(--spacing);
|
||||
font-weight: normal;
|
||||
|
||||
font-weight: 500;
|
||||
text-transform: uppercase;
|
||||
text-wrap: balance;
|
||||
max-width: 42ch;
|
||||
max-width: var(--max-w-content);
|
||||
color: var(--color-accent);
|
||||
}
|
||||
|
||||
.section-txt{
|
||||
max-width: var(--max-w-content);
|
||||
margin-inline: auto;
|
||||
|
||||
}
|
||||
|
||||
.subsection-w-media{
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: var(--padding-body);
|
||||
margin-bottom: calc(var(--spacing)*3);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
|
||||
.subsection-txt {
|
||||
max-width: var(--max-w-content);
|
||||
padding-left: var(--padding-inner);
|
||||
padding-right: var(--padding-inner);
|
||||
}
|
||||
|
||||
.media{
|
||||
margin-inline: auto;
|
||||
max-width: var(--max-w-content);
|
||||
padding-left: var(--padding-inner);
|
||||
padding-right: var(--padding-inner);
|
||||
position: sticky;
|
||||
top: 0px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
p {
|
||||
margin: calc(var(--spacing)*0.5) 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,9 +14,7 @@ export function report(responsiveSmall) {
|
|||
return;
|
||||
}
|
||||
|
||||
// Sur desktop : initMediaDisplay va gérer les media dynamiquement
|
||||
// Les swipers seront initialisés au moment de l'insertion dans #report__medias
|
||||
initMediaDisplay();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -33,188 +31,3 @@ function initSliderBeforeAfter(container = document){
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
function initMediaDisplay() {
|
||||
const reportMedias = document.querySelector('#report__medias');
|
||||
if (!reportMedias) return;
|
||||
|
||||
// Calculer la hauteur depuis les variables CSS: calc(var(--header-h) + var(--padding-body))
|
||||
const rootStyles = getComputedStyle(document.documentElement);
|
||||
const headerH = rootStyles.getPropertyValue('--header-h').trim();
|
||||
const paddingBody = rootStyles.getPropertyValue('--padding-body').trim();
|
||||
const spacingH = rootStyles.getPropertyValue('--spacing').trim();
|
||||
|
||||
|
||||
// Convertir en pixels si nécessaire
|
||||
const headerHPx = parseFloat(headerH);
|
||||
const paddingBodyPx = parseFloat(paddingBody);
|
||||
const spacingHPx = parseFloat(paddingBody);
|
||||
const totalOffset = headerHPx + paddingBodyPx + spacingHPx*5;
|
||||
|
||||
const sections = document.querySelectorAll('.section-content');
|
||||
const mediaElements = [];
|
||||
let mediaCounter = 0;
|
||||
|
||||
// 1. Pour chaque section, traiter les .media
|
||||
sections.forEach((section) => {
|
||||
const medias = section.querySelectorAll('.media');
|
||||
|
||||
medias.forEach((media) => {
|
||||
// Générer un ID unique si nécessaire
|
||||
if (!media.id) {
|
||||
media.id = `media-${mediaCounter++}`;
|
||||
}
|
||||
|
||||
// Créer une ancre
|
||||
const anchor = document.createElement('div');
|
||||
anchor.className = 'media-anchor';
|
||||
anchor.dataset.mediaId = media.id;
|
||||
anchor.innerHTML = '<span class="arrow-report">▶</span>'
|
||||
|
||||
// Vérifier si le media est précédé d'un titre
|
||||
let previousElement = media.previousElementSibling;
|
||||
let insertBeforeElement = media;
|
||||
|
||||
// Si l'élément précédent est un titre (h1-h6), insérer l'ancre avant le titre
|
||||
if (previousElement && /^H[1-6]$/.test(previousElement.tagName)) {
|
||||
insertBeforeElement = previousElement;
|
||||
}
|
||||
|
||||
// Insérer l'ancre
|
||||
insertBeforeElement.parentNode.insertBefore(anchor, insertBeforeElement);
|
||||
|
||||
// Stocker la référence pour l'observer
|
||||
mediaElements.push({
|
||||
anchor: anchor,
|
||||
media: media.cloneNode(true), // Cloner le media
|
||||
originalMedia: media,
|
||||
section: section
|
||||
});
|
||||
|
||||
// Masquer le media original
|
||||
media.style.display = 'none';
|
||||
});
|
||||
});
|
||||
|
||||
// 2. Fonction pour trouver et afficher le media le plus proche de la ligne de déclenchement
|
||||
let currentMediaId = null;
|
||||
let isUpdating = false; // Flag pour éviter les mises à jour simultanées
|
||||
|
||||
function updateActiveMedia() {
|
||||
// Éviter les mises à jour simultanées
|
||||
if (isUpdating) return;
|
||||
|
||||
// Trouver l'ancre qui est la plus proche de la ligne de déclenchement (totalOffset du haut)
|
||||
let closestAnchor = null;
|
||||
let closestDistance = Infinity;
|
||||
|
||||
mediaElements.forEach(({ anchor }) => {
|
||||
const rect = anchor.getBoundingClientRect();
|
||||
|
||||
// Si l'ancre est au-dessus ou à la ligne de déclenchement
|
||||
if (rect.top <= totalOffset) {
|
||||
const distance = totalOffset - rect.top;
|
||||
|
||||
// Prendre celle qui vient juste de passer (la plus proche en dessous de la ligne)
|
||||
if (distance < closestDistance) {
|
||||
closestDistance = distance;
|
||||
closestAnchor = anchor;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Si on a trouvé une ancre
|
||||
if (closestAnchor) {
|
||||
const mediaId = closestAnchor.dataset.mediaId;
|
||||
|
||||
// Si c'est déjà le media affiché, ne rien faire
|
||||
if (currentMediaId === mediaId) return;
|
||||
|
||||
// Trouver le media correspondant
|
||||
const mediaData = mediaElements.find(m => m.anchor === closestAnchor);
|
||||
|
||||
if (mediaData) {
|
||||
isUpdating = true;
|
||||
|
||||
// Utiliser requestAnimationFrame pour éviter les conflits de reflow
|
||||
requestAnimationFrame(() => {
|
||||
// Vider le conteneur
|
||||
reportMedias.innerHTML = '';
|
||||
|
||||
// Ajouter le nouveau media
|
||||
const newMediaElement = mediaData.media.cloneNode(true);
|
||||
reportMedias.appendChild(newMediaElement);
|
||||
currentMediaId = mediaId;
|
||||
|
||||
// Attendre le prochain frame pour initialiser les sliders/swipers
|
||||
requestAnimationFrame(() => {
|
||||
initSliderBeforeAfter(reportMedias);
|
||||
initSwipers(reportMedias);
|
||||
|
||||
// Débloquer les mises à jour après un court délai
|
||||
setTimeout(() => {
|
||||
isUpdating = false;
|
||||
}, 100);
|
||||
});
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// Aucune ancre n'a encore franchi la ligne, vider le conteneur
|
||||
if (currentMediaId !== null) {
|
||||
reportMedias.innerHTML = '';
|
||||
currentMediaId = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Écouter le scroll
|
||||
let scrollTimeout;
|
||||
window.addEventListener('scroll', () => {
|
||||
// Throttle pour optimiser les performances
|
||||
if (scrollTimeout) return;
|
||||
|
||||
scrollTimeout = setTimeout(() => {
|
||||
updateActiveMedia();
|
||||
scrollTimeout = null;
|
||||
}, 10);
|
||||
});
|
||||
|
||||
// Appeler une première fois au chargement
|
||||
updateActiveMedia();
|
||||
|
||||
// 4. Gérer les sections sans media immédiat
|
||||
// Observer aussi les sections elles-mêmes
|
||||
const sectionObserver = new IntersectionObserver((entries) => {
|
||||
entries.forEach(entry => {
|
||||
if (entry.isIntersecting) {
|
||||
const section = entry.target;
|
||||
|
||||
// Vérifier si cette section a un media juste après son premier titre
|
||||
const firstTitle = section.querySelector('h1, h2, h3, h4, h5, h6');
|
||||
if (firstTitle) {
|
||||
let nextElement = firstTitle.nextElementSibling;
|
||||
|
||||
// Chercher le prochain élément qui n'est pas une ancre
|
||||
while (nextElement && nextElement.classList.contains('media-anchor')) {
|
||||
nextElement = nextElement.nextElementSibling;
|
||||
}
|
||||
|
||||
// Si le prochain élément n'est pas un .media, vider #report__medias
|
||||
if (!nextElement || !nextElement.classList.contains('media')) {
|
||||
reportMedias.innerHTML = '';
|
||||
currentMediaId = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}, {
|
||||
root: null,
|
||||
rootMargin: `-${totalOffset}px 0px 0px 0px`,
|
||||
threshold: 0
|
||||
});
|
||||
|
||||
// Observer toutes les sections
|
||||
sections.forEach(section => {
|
||||
sectionObserver.observe(section);
|
||||
});
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue