Glossary: replace slider with auto-fit grid filling container width (like Action Plan)
This commit is contained in:
parent
97e5df11b2
commit
27e5307265
131
index.html
131
index.html
@ -858,79 +858,21 @@ main {
|
||||
|
||||
.tag.blue { background: rgba(0,102,204,0.1); color: var(--blue); }
|
||||
|
||||
/* ── GLOSSARY (horizontal slider) ── */
|
||||
.glossary-slider {
|
||||
margin-top: 40px;
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
/* ── GLOSSARY (auto-fit grid, fills container) ── */
|
||||
.glossary {
|
||||
display: flex;
|
||||
margin-top: 40px;
|
||||
display: grid;
|
||||
gap: 12px;
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
scroll-snap-type: x mandatory;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
padding-bottom: 8px;
|
||||
/* CRITICAL: constrain to parent so content overflows instead of expanding container */
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
max-width: 100%;
|
||||
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
|
||||
}
|
||||
|
||||
.glossary::-webkit-scrollbar { height: 6px; }
|
||||
.glossary::-webkit-scrollbar-track { background: transparent; }
|
||||
.glossary::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; }
|
||||
|
||||
.gloss-item {
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 12px;
|
||||
background: #fff;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
scroll-snap-align: start;
|
||||
min-height: 200px;
|
||||
flex: 0 0 280px; /* fixed card width, no shrinking */
|
||||
min-width: 280px;
|
||||
}
|
||||
@media (min-width: 640px) {
|
||||
.gloss-item { min-height: 220px; flex-basis: 320px; min-width: 320px; }
|
||||
}
|
||||
|
||||
/* nav controls: arrows + counter, centered below cards */
|
||||
.gloss-nav {
|
||||
margin-top: 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.gloss-nav-btn {
|
||||
width: 40px; height: 40px;
|
||||
border: 1px solid var(--border);
|
||||
background: #fff;
|
||||
border-radius: 50%;
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
cursor: pointer;
|
||||
transition: background 150ms ease, opacity 150ms ease, border-color 150ms ease;
|
||||
color: var(--text-65);
|
||||
}
|
||||
.gloss-nav-btn:hover:not(:disabled) {
|
||||
background: var(--blue);
|
||||
color: #fff;
|
||||
border-color: var(--blue);
|
||||
}
|
||||
.gloss-nav-btn:disabled { opacity: 0.3; cursor: not-allowed; }
|
||||
.gloss-nav-btn svg { width: 18px; height: 18px; }
|
||||
|
||||
.gloss-counter {
|
||||
font-size: 0.8125rem;
|
||||
color: var(--text-55);
|
||||
font-variant-numeric: tabular-nums;
|
||||
min-width: 64px;
|
||||
text-align: center;
|
||||
min-height: 160px;
|
||||
}
|
||||
|
||||
.gloss-trigger {
|
||||
@ -1610,18 +1552,7 @@ footer {
|
||||
без технического жаргона.
|
||||
</p>
|
||||
</div>
|
||||
<div class="glossary-slider">
|
||||
<div class="glossary" id="glossary-list"></div>
|
||||
<div class="gloss-nav">
|
||||
<button type="button" id="gloss-prev" class="gloss-nav-btn" aria-label="Назад">
|
||||
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="10,3 5,8 10,13"/></svg>
|
||||
</button>
|
||||
<span class="gloss-counter" id="gloss-counter">1 / 14</span>
|
||||
<button type="button" id="gloss-next" class="gloss-nav-btn" aria-label="Вперёд">
|
||||
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6,3 11,8 6,13"/></svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="glossary" id="glossary-list"></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@ -1916,56 +1847,6 @@ const SCHEDULE = [
|
||||
glossaryEl.appendChild(div);
|
||||
});
|
||||
|
||||
// Slider controls — index-based, uses scrollIntoView (more reliable than scrollTo with snap)
|
||||
const glossPrev = document.getElementById('gloss-prev');
|
||||
const glossNext = document.getElementById('gloss-next');
|
||||
const glossCounter = document.getElementById('gloss-counter');
|
||||
const cards = Array.from(glossaryEl.querySelectorAll('.gloss-item'));
|
||||
const totalCards = cards.length;
|
||||
let currentIdx = 0;
|
||||
|
||||
function goTo(i) {
|
||||
currentIdx = Math.max(0, Math.min(totalCards - 1, i));
|
||||
cards[currentIdx].scrollIntoView({ behavior: 'smooth', inline: 'start', block: 'nearest' });
|
||||
updateNavState();
|
||||
}
|
||||
function updateNavState() {
|
||||
glossCounter.textContent = `${currentIdx + 1} / ${totalCards}`;
|
||||
glossPrev.disabled = currentIdx === 0;
|
||||
glossNext.disabled = currentIdx === totalCards - 1;
|
||||
}
|
||||
// Sync currentIdx when user scrolls manually (touch/trackpad)
|
||||
function syncFromScroll() {
|
||||
const containerLeft = glossaryEl.getBoundingClientRect().left;
|
||||
let bestIdx = 0, bestDist = Infinity;
|
||||
for (let i = 0; i < cards.length; i++) {
|
||||
const d = Math.abs(cards[i].getBoundingClientRect().left - containerLeft);
|
||||
if (d < bestDist) { bestDist = d; bestIdx = i; }
|
||||
}
|
||||
if (bestIdx !== currentIdx) {
|
||||
currentIdx = bestIdx;
|
||||
updateNavState();
|
||||
}
|
||||
}
|
||||
|
||||
glossPrev.addEventListener('click', () => {
|
||||
console.log('[gloss] prev clicked, was idx=' + currentIdx);
|
||||
goTo(currentIdx - 1);
|
||||
});
|
||||
glossNext.addEventListener('click', () => {
|
||||
console.log('[gloss] next clicked, was idx=' + currentIdx);
|
||||
goTo(currentIdx + 1);
|
||||
});
|
||||
glossaryEl.addEventListener('scroll', syncFromScroll, { passive: true });
|
||||
|
||||
// Defer to ensure layout is settled before reporting/computing metrics
|
||||
requestAnimationFrame(() => {
|
||||
console.log('[gloss] slider init: cards=' + totalCards +
|
||||
' scrollWidth=' + glossaryEl.scrollWidth +
|
||||
' clientWidth=' + glossaryEl.clientWidth +
|
||||
' canScroll=' + (glossaryEl.scrollWidth > glossaryEl.clientWidth));
|
||||
updateNavState();
|
||||
});
|
||||
|
||||
// Render projects
|
||||
const projectsEl = document.getElementById('projects-grid');
|
||||
|
||||
Reference in New Issue
Block a user