Вертикальная Прокрутка Меню Css

#javascript #css

Вопрос:

Я хочу создать вертикальный выбор, как на изображении ниже, кто-нибудь может мне помочь?

введите описание изображения здесь

Я пытался сделать один, но нет, результат не тот, что я хочу, активный класс не находится посередине между стрелками при прокрутке.

  const div = document.querySelectorAll("#menulist");
    const atag = document.querySelectorAll("#list");
    var curLen = 0;
    let len = atag.length;
    function activeMenu(){
      debugger
      if(event.wheelDelta > 0){
        if(curLen > 0){
          curLen --;
        }       
        atag.forEach(ltx => ltx.classList.remove("active"));
        atag[curLen].classList.add("active");
      } else {
        if((len - curLen) > 1){
          curLen   ;
        }       
        atag.forEach(ltx => ltx.classList.remove("active"));
        atag[curLen].classList.add("active");
      }
    }
    window.addEventListener('wheel', activeMenu); 
 .menuBox {
    margin: 0 auto;
    width:100%;
    margin: 23em 0 0 0;
}
.vertical-menu {
    display: flex;
    float:left;
  height: 450px;    
}
.vertical-menu:after {
    display: block;
    content: '';
    clear: both;
}
.vertical-menu .list{
    margin-top:-100px;
    text-align:center;
    display:inline-block;
    font-size:var(--small-font-size);
    overflow-y: auto;
    width:100%;
    /*  scroll-snap-type: y mandatory; */
    -ms-overflow-style: none;
}
.vertical-menu .list a.active {
    background-color: #fff;
    color:#000;
    font-weight: bold; 
    font-size:var(--menulist-font-size);
}
.vertical-menu .list::-webkit-scrollbar{ display:none; }
.vertical-menu .left{
    display:inline-block;
    text-align:center;
    font-size:50px;
    widht:10%;
}
.vertical-menu .right{
    display:inline-block;
    text-align:center;
    font-size:50px;
    widht:10%;
}

.vertical-menu a {
    font-family: fantasy;
      background-color: #fff;
      color: #bbbbbb;
      display: block;
      padding: 12px;
      text-decoration: none;
}
.vertical-menu a:hover {
  /* background-color: #fff;
  color:#000;
  font-weight: bold; */
}
.vertical-menu a.active {
    background-color: #fff;
    color:#000;
    font-weight: bold; 
    font-size:50px;
}
.vertical-icon {
    width:40%;
    text-align:center;
    align-items:center;
    display: flex;
    justify-content:center;
    margin: 0 0 0 0;
} 
 <div class="menuBox">
    <div class="vertical-menu align-self-center">
        <div class="vertical-menu left"><a href="#"><</a></div>
            <div id="menulist" class="vertical-menu list" style="display:inline !important;">
                <a id="list" href="#" >Home</a>
                <a id="list" href="#" >TPHO Receive</a>
                <a id="list" href="#" >PO Completion</a>
                <a id="list" href="#" >HQ Revision</a>
                <a id="list" href="#" >Pre-BOM</a>
                <a id="list" href="#" >CR2 BOM</a>
                <a id="list" href="#" >Final BOM</a>
                <a id="list" href="#" >Upper Mold</a>
                <a id="list" href="#" >Bottom Mold</a>
            </div> 
        <div class="vertical-menu right"><a href="#">></ion-icon></a></div>
    </div>
</div> 

на самом деле я хочу сделать этот компонент в vue, но сначала я хочу попробовать его с помощью css и js, а затем я настрою его в vue. но мои навыки css плохие.

или есть библиотека выбора, подобная представлению, которое я хочу видеть выше? похоже, так будет проще

Ответ №1:

Я отредактировал ваш код, чтобы получить тот же результат, что и на изображении выше.

  1. .стрелки меню и .список меню должны быть в position: absolute
  2. Найдите начальную позицию в списке .menu в центре окна .menu со свойством top: calc()
  3. Затем в javascript определите начальную позицию по индексу
  4. Поместите результат вычисления в .меню-список со стилем преобразования
 const menuList = document.querySelector('.menu-list')
const atag = document.querySelectorAll(".list");
let curLen = 4; // Set index for active class
let len = atag.length;

// Add class 'active' to the 'home' when page loaded
atag[curLen].classList.add('active')
// Get the current fixed height of the list class
const heightActiveClass = atag[curLen].getBoundingClientRect().height
// Multuply current index element with fixed height
const startYPos = curLen * heightActiveClass
// Set result number in style
menuList.style.transform = `translate(-50%, -${startYPos}px)`


function activeMenu(event) {
  if (event.wheelDelta > 0) {
    if (curLen > 0) curLen--
      setActiveLinkWithArrows(atag)
  } else {
    if ((len - curLen) > 1) curLen  
      setActiveLinkWithArrows(atag)
  }
}

function setActiveLinkWithArrows(arr) {
  arr.forEach((el, idx) => {
    if (curLen === idx) {
      el.classList.add("active")
      // Multuply current index element with fixed height
      const yPos = idx * heightActiveClass
      // Set result number in style
      menuList.style.transform = `translate(-50%, -${yPos}px)`
      return
    }
    el.classList.remove("active")
  });
}
window.addEventListener('wheel', activeMenu); 
 *,
::after,
::before {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

:root {
  --menubox-height: 400px;
  --list-heigth: 50px;
}

body {
  width: 100vw;
  height: 100vh;
  display: grid;
  place-items: center;
  color: aliceblue;
  background-color: hsl(0, 0%, 100%);
  position: relative;
  overflow-x: hidden;
}

a {
  font-family: fantasy;
  text-decoration: none;
  color: hsl(0, 0%, 73%);
}

.menu-box {
  width: 250px;
  height: var(--menubox-height);
  display: flex;
  justify-content: center;
  position: relative;
  overflow: hidden;
}

.menu-box::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(
    to bottom,
    hsl(0 0% 100%) 0%,
    hsl(0 0% 0% / 0) 50%,
    hsl(0 0% 100%) 100%
  );
  z-index: 10;
  pointer-events: none;
}

.menu-list {
  width: 80%;
  display: flex;
  flex-flow: column;
  text-align: center;
  font-size: 1rem;
  position: absolute;
  top: calc(var(--menubox-height) / 2 - var(--list-heigth) / 2);
  left: 50%;
  transform: translate(-50%, 0);
  transition: transform 0.3s ease-in-out;
}

.list {
  height: var(--list-heigth);
  position: relative;
  padding: 12px;
  transition: all 0.3s ease-in-out;
}

.list.active {
  color: hsl(0, 0%, 0%);
  font-size: 1.3rem;
}

.menu-arrows {
  width: 100%;
  height: var(--list-heigth);
  display: flex;
  justify-content: space-between;
  position: absolute;
  top: 50%;
  font-size: 3rem;
  pointer-events: none;
  transform: translateY(-50%);
}
.arrow-left,
.arrow-right {
  pointer-events: all;
}
.arrow-left a,
.arrow-right a {
  color: hsl(0, 0%, 48%);
  position: relative;
  top: -5px;
  transition: all 0.3s ease-in-out;
}
.arrow-left:hover a,
.arrow-right:hover a {
  color: hsl(0, 0%, 0%);
  position: relative;
  top: -5px;
} 
 <div class="menu-box">
  <div class="menu-list">
    <a class="list" href="#home">Home</a>
    <a class="list" href="#">TPHO Receive</a>
    <a class="list" href="#">PO Completion</a>
    <a class="list" href="#">HQ Revision</a>
    <a class="list" href="#">Pre-BOM</a>
    <a class="list" href="#">CR2 BOM</a>
    <a class="list" href="#">Final BOM</a>
    <a class="list" href="#">Upper Mold</a>
    <a class="list" href="#">Bottom Mold</a>
  </div>
  <div class="menu-arrows">
    <div class="arrow-left">
      <a href="#left">
        <</a>
    </div>
    <div class="arrow-right"><a href="#right">></a></div>
  </div>
</div> 

Комментарии:

1. Удивительно,я не подумал о том, чтобы установить верх, спасибо за помощь