Glossary: convert grid to horizontal scroll-snap slider with prev/next buttons
This commit is contained in:
parent
2e7959607e
commit
e0daa85982
84
index.html
84
index.html
@ -764,14 +764,25 @@ main {
|
||||
|
||||
.tag.blue { background: rgba(0,102,204,0.1); color: var(--blue); }
|
||||
|
||||
/* ── GLOSSARY ── */
|
||||
.glossary {
|
||||
/* ── GLOSSARY (horizontal slider) ── */
|
||||
.glossary-slider {
|
||||
margin-top: 40px;
|
||||
display: grid;
|
||||
gap: 12px;
|
||||
grid-template-columns: 1fr;
|
||||
position: relative;
|
||||
}
|
||||
@media (min-width: 768px) { .glossary { grid-template-columns: repeat(2, 1fr); } }
|
||||
|
||||
.glossary {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
overflow-x: auto;
|
||||
scroll-snap-type: x mandatory;
|
||||
scroll-behavior: smooth;
|
||||
scroll-padding-left: 8px;
|
||||
padding: 4px 4px 16px; /* breathing room + scrollbar gutter */
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
.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);
|
||||
@ -779,7 +790,34 @@ main {
|
||||
background: #fff;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 0 0 280px; /* fixed card width */
|
||||
scroll-snap-align: start;
|
||||
min-height: 180px;
|
||||
}
|
||||
@media (min-width: 640px) { .gloss-item { flex-basis: 320px; min-height: 200px; } }
|
||||
|
||||
/* nav buttons */
|
||||
.gloss-nav {
|
||||
display: none; /* mobile: rely on swipe */
|
||||
position: absolute;
|
||||
top: -52px; right: 0;
|
||||
gap: 8px;
|
||||
}
|
||||
@media (min-width: 640px) { .gloss-nav { display: flex; } }
|
||||
|
||||
.gloss-nav-btn {
|
||||
width: 36px; height: 36px;
|
||||
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;
|
||||
color: var(--text-65);
|
||||
}
|
||||
.gloss-nav-btn:hover:not(:disabled) { background: var(--hover); color: var(--text); }
|
||||
.gloss-nav-btn:disabled { opacity: 0.3; cursor: not-allowed; }
|
||||
.gloss-nav-btn svg { width: 16px; height: 16px; }
|
||||
|
||||
.gloss-trigger {
|
||||
width: 100%;
|
||||
@ -1396,7 +1434,17 @@ footer {
|
||||
без технического жаргона.
|
||||
</p>
|
||||
</div>
|
||||
<div class="glossary" id="glossary-list"></div>
|
||||
<div class="glossary-slider">
|
||||
<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>
|
||||
<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 class="glossary" id="glossary-list"></div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@ -1660,7 +1708,7 @@ const SCHEDULE = [
|
||||
scheduleEl.appendChild(div);
|
||||
});
|
||||
|
||||
// Render glossary (always-expanded cards, two-column grid)
|
||||
// Render glossary as horizontal slider with prev/next buttons
|
||||
const glossaryEl = document.getElementById('glossary-list');
|
||||
GLOSSARY.forEach(item => {
|
||||
const div = document.createElement('div');
|
||||
@ -1679,6 +1727,26 @@ const SCHEDULE = [
|
||||
glossaryEl.appendChild(div);
|
||||
});
|
||||
|
||||
// Slider controls
|
||||
const glossPrev = document.getElementById('gloss-prev');
|
||||
const glossNext = document.getElementById('gloss-next');
|
||||
function scrollByCard(direction) {
|
||||
const firstCard = glossaryEl.querySelector('.gloss-item');
|
||||
if (!firstCard) return;
|
||||
const step = firstCard.getBoundingClientRect().width + 12; // card + gap
|
||||
glossaryEl.scrollBy({ left: direction * step, behavior: 'smooth' });
|
||||
}
|
||||
function updateGlossNav() {
|
||||
const maxScroll = glossaryEl.scrollWidth - glossaryEl.clientWidth - 2;
|
||||
glossPrev.disabled = glossaryEl.scrollLeft <= 2;
|
||||
glossNext.disabled = glossaryEl.scrollLeft >= maxScroll;
|
||||
}
|
||||
glossPrev.addEventListener('click', () => scrollByCard(-1));
|
||||
glossNext.addEventListener('click', () => scrollByCard(1));
|
||||
glossaryEl.addEventListener('scroll', updateGlossNav, { passive: true });
|
||||
window.addEventListener('resize', updateGlossNav);
|
||||
updateGlossNav();
|
||||
|
||||
// Render projects
|
||||
const projectsEl = document.getElementById('projects-grid');
|
||||
PROJECTS.forEach(item => {
|
||||
|
||||
Reference in New Issue
Block a user