웹프로그래밍/JavaScript

프로그래밍 언어 응용 35일차 (24/12/30)

wkun 2024. 12. 30. 17:57

CONTENTS

 

기능구현

1)slider

2)tab

 

 

----------------------------------------------------------------

 

 

기능구현

 

1)slider

 

<html>

    <body>
        <div id="slidebox">
            <!-- 컨텐츠부 -->
            <ul id="sliders">
                <li><img src="./img/slide01.jpg" alt></li>
                <li><img src="./img/slide02.jpg" alt></li>
                <li><img src="./img/slide03.jpg" alt></li>
            </ul>
            <!-- 버튼부 -->
            <div id="buttons">
                <img src="./img/left.png" class="left">
                <img src="./img/right.png" class="right">
            </div>
        </div>
    </body>

 

<css>

/* CSS 초기화 작업 */
*{
    margin:0;
    padding: 0;
    box-sizing: border-box;
    list-style: none;
    text-decoration: none;
}
/* slidebox 작업 */
#slidebox{
    border: 1px solid red;
    width: 60%; /* 부모 사이즈의 60%, 슬라이드를 보여주기위해서 설정*/
    margin: 0 auto; /*부모보다 작을 경우 가로 마진이 생성, 이때 auto를 통해서 좌우 n빵 */
    overflow: hidden;
    position: relative; /*좌우버튼 absolute의 기준을 설정*/
    white-space: nowrap; /*자식의 인라인 속성을 가지면 부모를 넘어가는 것을 허락함*/
}
#slidebox ul {
    width: 100%;
    font-size: 0; /*자식 li간의 미세한 띄움을 없앰*/
}
#slidebox ul li{
    width: 100%;
    display: inline-block;/*li의 요소를 가로로배치하기위해 inline-block으로 변경*/

    transition: all 3s; /*자바스크립트로 움직일때 부드럽게 움직이게한다*/
}
#slidebox ul li img{
    width: 100%;
}

/*좌우버튼 설정*/
#buttons {
    width: 100%;
    position: absolute;
    top: 50%;  /*부모로 부터 50% 내려옴 중앙 아님*/
    transform: translateY(-50%); /*자신의 사이즈 만큼 50% 위로 올라감 , 중앙정렬됨*/
    display: flex; /*플렉스를 통하여 이미지 두개를 가로로 배치*/
    justify-content: space-between; /*가로로 배치된 이미지를 양끝정렬 시킴*/
}
#buttons img{
    width: 10%; /*이미지의 사이즈를 조절*/
}

 

<js>

// Step 1 Selector
// 좌우 이미지에 클래스 .left 와 .right를 먼저 할당한다
var left = document.querySelector(".left");
var right = document.querySelector(".right");
console.log(left);
console.log(right);

var lis = document.querySelectorAll('#sliders li');
console.log(lis);

// Step 2 이벤트 할당
left.addEventListener("click", leftsliding);
right.addEventListener("click", rightsliding);
//Step 4 전역변수 선언
var index = 0;
// Step 3 함수생성
//
//1번째 : translateX(0%); 0 * -100
//2번째 : translateX(-100%); 1* -100
//3번째 : translateX(-200%); 2* -100
function leftsliding() {
    index = index - 1;
    // 음수값이되면 안되므로 li의 갯수 값을 넣어줌 현재는 2
    console.log(lis.length);
    if (index < 0) {
        index = (lis.length - 1); //2을 입력
    }
    console.log("슬라이딩함수");
    console.log(index);
    lis.forEach(function (slide) {
        //li태그.style.transform = translateX()
        slide.style.transform = `translateX(${index * (-100)}%)`;
    });  
    //translateX(-200%)와 같음, ${}는 문자 안에서 수식을 계산하는 방법임
    // sliding(index); //현재 index 값을 가지고 sliding 함수로 이동
}
function rightsliding() {
    index = index + 1;
    // 마지막 슬라이더 번호보다 크다면 안됨
    if (index >= (lis.length)) {
        index = 0; //3을 입력
    }
    console.log("슬라이딩함수");
    console.log(index);
    lis.forEach(function (slide) {
        //li태그.style.transform = translateX()
        slide.style.transform = `translateX(${index * (-100)}%)`;
    });
   
    // sliding(index); //현재 index 값을 가지고 sliding 함수로 이동
}
function sliding(value) {
    console.log("슬라이딩함수");
    console.log(value);
    lis.forEach(function (slide) {
        slide.style.transform = `translateX(-${value * 100}%)`;
    });  //translateX(-200%)와 같음, ${}는 문자 안에서 수식을 계산하는 방법임
}

 

 

예제1)

 

<html>

  <body>
    <section id="main">
      <div class="slidebox">
        <div class="slides">
          <div class="slide">
            <div class="main_banner container">
              <div class="main_text_box">
                <h1>Repr in voluptate</h1>
                <h2>Ullamco laboris nisi ut</h2>
                <p>We bring you 100% free CSS templates for your websites. If you wish <br>to support TemplateMo, please make a small contribution via PayPal or tell <br>your friends about our website. Thank you.</p>
              </div>
              <div class="main_img_box">
                <img src="./img/banner_img_01.jpg" alt="light">
              </div>
            </div>
          </div>
          <div class="slide">
            <div class="main_banner container">
              <div class="main_text_box">
                <h1>Repr in voluptate</h1>
                <h2>Ullamco laboris nisi ut</h2>
                <p>We bring you 100% free CSS templates for your websites. If you wish <br>to support TemplateMo, please make a small contribution via PayPal or tell <br>your friends about our website. Thank you.</p>
              </div>
              <div class="main_img_box">
                <img src="./img/banner_img_02.jpg" alt="light">
              </div>
            </div>
          </div>
          <div class="slide">
            <div class="main_banner container">
              <div class="main_text_box">
                <h1>Repr in voluptate</h1>
                <h2>Ullamco laboris nisi ut</h2>
                <p>We bring you 100% free CSS templates for your websites. If you wish <br>to support TemplateMo, please make a small contribution via PayPal or tell <br>your friends about our website. Thank you.</p>
              </div>
              <div class="main_img_box">
                <img src="./img/banner_img_03.jpg" alt="light">
              </div>
            </div>
          </div>
        </div>
      </div>

      <div class="control_box">
        <i class="fa-solid fa-chevron-left left"></i>
        <i class="fa-solid fa-chevron-right right"></i>
      </div>
      <div class="slide_btn">
        <label for="slide01"></label>
        <label for="slide02"></label>
        <label for="slide03"></label>
      </div>
    </section>
  </body>

 

<css>

*{
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  text-decoration: none;
  list-style: none;
  color: inherit;
}

.container {
  width: 70%;
  margin: 0 auto;
  /* border: 1px solid blue; */
}

/* css작업순서 : 큰 레이아웃에서 작은 레이아웃으로, 위에서 아래로 */
/*
[요소 선택할 때마다 공통 질문]
1. 부모에서 자식 정렬 (큰 정렬) 필요하나
  - display:flex; 관련
2. 세부 정렬 필요하나? margin/padding
3. 크기 지정 필요하나? width/height
4, 요소 위에 띄워야하나?
  - position:absolute;
*/

/* main section 시작 */
/* #main
1번질문) 큰정렬 필요없음
- 이유 : radio버튼은 없앨거고, .slide_btn은 absolute할거라 정렬할 자식이 하나밖에 안 남음
2번질문) 세부정렬 필요함
- 이유 : 화면 상하좌우에 요소들이 너무 딱 붙어있어서 몸집을 키울거임 : padding
3번질문) 크기지정 필요없음
- 이유 : 기본 width:100%;라 안 줘도 됨
4번질문) absolute 필요없음
- 이유 : 기준점이 될 필요는 있겠으나 #main 자체를 띄울 필요가 없음. (참고로 기준점은 나중에 줘도 됨)
*/
#main{
  padding: 20px;
  background-color: #efefef;
  position: relative;
}

/* #main이 끝났으니 그다음은 input:radio 관련인데 제일 마지막 순서에 display:none; 할거라 지금 순서에 필요없음
*/
/* 그다음 순서인 .slidebox
1번질문) 큰정렬 필요없음
- 이유 : 정렬할 자식이 하나밖에 없어서 굳이
2번질문) 세부정렬 필요없음
- 이유 : 시각적으로 답답한 부분은 안 보임
3번질문) 크기지정 필요함
- 이유 : width:100%;는 안 줘도 되지만 콘텐츠를 볼 화면이므로 명확하게 하기 위함.
4번질문) absolute 필요없음
- 이유 : .slidebox를 붕 띄워야 하는 이유가 없어서
*/
#main .slidebox {
  width: 100%;
  /* border: 1px solid black; */
  white-space: nowrap;
  overflow: hidden;
}

/* 그다음 순서인 .slides
1번질문) 큰정렬 필요없음
- 이유 : display:flex;하면 오히려 자식들이 짜부러져서 필요없음
2번질문) 세부정렬 필요없음
- 이유 : 시각적으로 답답한 부분은 안 보임
3번질문) 크기지정 필요없음
- 이유 : width:100%;는 안 줘도 됨
4번질문) absolute 필요없음
- 이유 : .slides를 붕 띄워야 하는 이유가 없어서
*/
#main .slidebox .slides {
font-size: 0;
}

/* 그다음 순서인 .slide
1번질문) 큰정렬 필요함
- 이유 : display:inline-block; 사용
2번질문) 세부정렬 필요없음
- 이유 : 시각적으로 답답한 부분은 안 보임
3번질문) 크기지정 필요함
- 이유 : width:100%;는 안 줘도 되지만 명확하게 하기 위함.
4번질문) absolute 필요없음
- 이유 : .slide를 붕 띄워야 하는 이유가 없어서
*/
#main .slidebox .slides .slide {
  font-size: 16px;
  /* 바로 위 코드 .slides에서 공백문자 없애려고 font-size:0px로 줬기 때문에 공백문자 외의 글자의 사이즈 되돌리기 위함 */
  width: 100%;
  display: inline-block;
  /* border: 1px solid red; */

  position: relative;
  transition: all 2s;
}

/* 그다음 순서인 label
1번질문) 큰정렬 필요없음
- 이유 : 자식 요소가 이미지 혹은 아이콘이 될건데 가로정렬할 거는 없음
2번질문) 세부정렬 필요없음
- 이유 : 시각적으로 답답한 부분은 안 보임
3번질문) 크기지정 필요없음
- 이유 : width, height는 필요없으나 font-size로 사이즈 키워도 됨
4번질문) absolute 필요함
- 이유 : zay사이트에서는 요소 위 배치하는 것이 아니라 필요없을 수 있지만 수월한 가로,세로 배치를 위해 사용
*/
#main .control_box i {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);

  font-size: 50px;
  color: gray;
  border: transparent;
  cursor: pointer;
}

/* 왼쪽 라벨 위치 지정 */
#main .left{
  left: 0;
}

/* 오른쪽 라벨 위치 지정 */
#main .right{
  right: 0;
}

/* 여기서부터 콘텐츠 내부 정렬 시작 */
#main .main_banner {
  display: flex;
  justify-content: center;
  white-space: wrap;
  /* background-color: red; */
}

#main .main_banner .main_text_box {
  width: 50%;
  display: flex;
  flex-direction: column;
  justify-content: center;
  margin-right: 20px;
  /* background-color: blue; */
}

#main .main_banner .main_img_box {
  width: 50%;
}

#main .main_banner .main_img_box img{
  width: 100%;
  height: 100%;
}

/* 슬라이더 크기 지정 및 정렬, 라벨 배치, 콘텐츠 정렬 및 배치 완료 */

/* 여기서부터 슬라이더 기능부 */
/* 특정 input:radio가 checked 됐을 때 지정한 요소의 속성값 변경하기 */
/* 속성값 변경하려는 요소는 특정 input:radio의 형제에서 타고 들어가야함. (input태그는 자식을 가질 수 없으므로)

- 선택자 기본 원칙 : 부모에서 자식으로 접근 가능(후손선택자/자식선택자), 형제는 같은 라인이면서 아래 방향으로 접근 가능(역으로 위로 접근 불가)
*/
/* #main input[id="slide01"]:checked ~ .slidebox .slide {
  transform: translateX(0%);
}
#main input[id="slide02"]:checked ~ .slidebox .slide {
  transform: translateX(-100%);
}
#main input[id="slide03"]:checked ~ .slidebox .slide {
  transform: translateX(-200%);
} */

/* 메인 섹션 밑부분 라벨 작업 시작 */
/* 크기 지정 및 위치 조정 */
#main .slide_btn{
  width: 20%;
  position: absolute;
  bottom: 4%;
  left: 50%;
  transform: translateX(-50%);
  text-align: center;
}

#main .slide_btn label {
  display: inline-block;
  width: 20%;
  height: 8px;
  margin-right: 5px;
  background-color: #99d4a7;
  cursor: pointer;
}

#main input[id="slide01"]:checked ~ .slide_btn label[for="slide01"] {
  background-color: #59ab6e;
}
#main input[id="slide02"]:checked ~ .slide_btn label[for="slide02"] {
  background-color: #59ab6e;
}
#main input[id="slide03"]:checked ~ .slide_btn label[for="slide03"] {
  background-color: #59ab6e;
}

 

<js>

//1.selector
//처음만 선택됨
let left = document.querySelector(".left");
let right = document.querySelector(".right");

console.log(left);
console.log(right);

let slides = document.querySelectorAll(".slide");

//2. 이벤트 할당

left.addEventListener("click", leftsliding);
right.addEventListener("click", rightsliding);

let index = 0;

//3.함수 선언
function leftsliding() {
  //4.함수 기능 정의
  /*
  최종목적
  왼쪽 버튼 누를 때 슬라이드 컨텐츠들이 다 이동한다.
  index*(-100)%
  0번째 콘텐츠: 0% : 0 * -100
  1번째 콘텐츠: -100% :1 *-100
  2번째 콘텐츠: -200% : 2 * -200
  */
  index = index -1; //index--;
  if(index < 0) {
    index = (slides.length -1);
  }

  //콘텐츠 묶음 > 요소 3개 : NodeList객체->forEach메서드
  slides.forEach(function(slide){ //value, index, array
    //div.slide(div인데 class가 slide인 요소)
    console.log(slide);
    slide.style.transform = `translateX(${index*(-100)}%)`;
  });
}

function rightsliding() {
  index = index +1;
 
  if(index >= (slides.length)) {
    index = 0;
  }
  slides.forEach(function(slide){
    slide.style.transform = `translateX(${index*(-100)}%)`;
  });
}

function sliding(value) {
  slides.forEach(function (slide) {
      slide.style.transform = `translateX(${value * -100}%)`;
  });  
}

 

예제2)

 

<html>

<body>
    <header class="container">
      <div class="logo">
        Feane
      </div>
      <nav>
        <ul>
          <li><a href="#">HOME</a></li>
          <li><a href="#">MENU</a></li>
          <li><a href="#">ABOUT</a></li>
          <li><a href="#">BOOKTABLE</a></li>
        </ul>
      </nav>
      <div class="icon_box">
        <i class="fa-solid fa-user"></i>
        <i class="fa-solid fa-cart-shopping"></i>
        <i class="fa-solid fa-magnifying-glass"></i>
        <a href="#">Order Online</a>
      </div>
    </header>

    <section id="main">
      <img src="./images/hero-bg.jpg" alt>
      <!-- 보여질 화면 -->
      <div class="slidebox">
        <!-- 콘텐츠들의 묶음 -->
        <div class="slides">
          <!-- 각 콘텐츠 1,2,3 -->
          <div class="slide">
            <h1>Fast Food Restaurant</h1>
            <p>Doloremque, itaque aperiam facilis rerum, commodi, temporibus
              sapiente ad <br>mollitia laborum quam quisquam esse error unde.
              Tempora ex doloremque, labore, <br>sunt repellat dolore, iste
              magni
              quos nihil ducimus libero ipsam.</p>
            <a href="#">Order Now</a>
          </div>
          <div class="slide">
            <h1>Fast Food Restaurant</h1>
            <p>Doloremque, itaque aperiam facilis rerum, commodi, temporibus
              sapiente ad <br>mollitia laborum quam quisquam esse error unde.
              Tempora ex doloremque, labore, <br>sunt repellat dolore, iste
              magni
              quos nihil ducimus libero ipsam.</p>
            <a href="#">Order Now</a>
          </div>
          <div class="slide">
            <h1>Fast Food Restaurant</h1>
            <p>Doloremque, itaque aperiam facilis rerum, commodi, temporibus
              sapiente ad <br>mollitia laborum quam quisquam esse error unde.
              Tempora ex doloremque, labore, <br>sunt repellat dolore, iste
              magni
              quos nihil ducimus libero ipsam.</p>
            <a href="#">Order Now</a>
          </div>
        </div>
      </div>
      <div class="slidebtn">
        <label id="label0" for="s01"></label>
        <label id="label1" for="s02"></label>
        <label id="label2" for="s03"></label>
      </div>
    </section>

 

<css>


* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  text-decoration: none;
  list-style: none;
  color: inherit;
}

.container {
  width: 70%;
  margin: 0 auto;
}

/* header start */
header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  color: white;
  /* background-color: black; */
  padding: 20px;
  position: absolute;
  top: 0;
  left: 50%;
  transform: translateX(-50%);
  z-index: 99;
}

header .logo {
  font-family: "Dancing Script", cursive;
  font-optical-sizing: auto;
  font-weight: 400;
  font-style: normal;
  font-size: 32px;
}

header nav {
  width: 30%;
}

header nav ul {
  display: flex;
  justify-content: space-between;
}

header nav ul li:nth-child(1) {
  color: #ffbe33;
}

header .icon_box i {
  margin-right: 10px;
}

header .icon_box a {
  display: inline-block;
  padding: 10px 20px;
  background-color: #ffbe33;
  border-radius: 20px;
}

/* main section start */
#main {
  position: relative;
  color: white;
}

#main input[type="radio"] {
  display: none;
}

#main > img {
  width: 100%;
}

#main .slidebox {
  width: 85%;
  position: absolute;
  top: 50%;
  left: 15%;
  transform: translateY(-50%);

  white-space: nowrap;
  overflow: hidden;
}

#main .slidebox .slides {
  font-size: 0px;
}

#main .slidebox .slides .slide {
  width: 100%;
  display: inline-block;
  font-size: 16px;
  white-space: wrap;

  /* border: 2px solid red; */
  transition: all 1s;
}

#main .slide h1{
  font-family: "Dancing Script", cursive;
  font-optical-sizing: auto;
  font-weight: 400;
  font-style: normal;
  font-size: 56px;
  margin-bottom: 10px;
}

#main .slide p{
  font-size: 14px;
  margin-bottom: 10px;
}

#main .slide a {
  display: inline-block;
  padding: 10px 30px;
  background-color: #ffbe33;
  border-radius: 20px;
}

#main .slidebtn {
  position: absolute;
  bottom: 10%;
  left: 15%;
}

#main .slidebtn label{
  display: inline-block;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background-color: white;
}

#main .slidebtn label.active {
  background-color: #ffbe33;
}

 

<js>

// Step1. 요소 선택하기
let btns = document.querySelectorAll('.slidebtn label');
let slides = document.querySelectorAll('.slide');

// Step2. 이벤트 할당하기
btns.forEach(function(btn){ //value : label요소
  btn.addEventListener('click',sliding);
  //콘텐츠 슬라이딩 하는 기능
  btn.addEventListener('click',function(){
   changeColor(this);
  });
  //버튼(라벨) 클릭했을 때, 배경색상 노란색으로 바꾸기
});

let index = 0;
changeColor(btns[0]);

function sliding(){
  index = parseInt(this.id.charAt(this.id.length-1));
  console.log(index);

  slides.forEach(function(slide){
    slide.style.transform = `translateX(${index*(-100)}%)`;
  });
}

//선택한 라벨 배경색상만 노란색으로 바꾸기 : .active
// background-color : yellow;
function changeColor(activeBtn){
  btns.forEach(function(btn){
    btn.classList.remove('active');
  });
  activeBtn.classList.add('active');
}

 

 

2)tab

 

<html>

<body>
  <!-- 탭 메뉴 -->
  <div>
    <div class="tab" id="tab1">탭 1</div>
    <div class="tab" id="tab2">탭 2</div>
    <div class="tab" id="tab3">탭 3</div>
  </div>
  <!-- 탭 컨텐츠 -->
  <div class="tab-content" id="content1">탭 1 내용</div>
  <div class="tab-content" id="content2">탭 2 내용</div>
  <div class="tab-content" id="content3">탭 3 내용</div>
</body>

 

<css>

*{
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  list-style: none;
  text-decoration: none;
}

.tab {
  display: inline-block;
  padding: 10px 20px;
  cursor: pointer;
  background-color: #f1f1f1;
  border: 1px solid #ccc;
}

.tab-content {
  display: none;
  padding: 20px;
  border: 1px solid #ccc;
}

.active {
  background-color: #ccc;
}

.show {
  display: block;
}

 

<js>

1)

// 탭 클릭 이벤트 추가
//step1. 셀렉트하기
var tabs = document.querySelectorAll('.tab');
//NodeList객체 : 배열은 아닌데 배열처럼 쓸 수 있다.

//step2. 이벤트 할당하기
for (var i = 0; i < tabs.length; i++) {
  tabs[i].addEventListener('click', tabIdCalculator); //탭메뉴-탭컨텐츠 연결작업
}

//탭메뉴-탭컨텐츠 연결작업 : id속성
function tabIdCalculator() {
  var tabId = 'content' + this.id.charAt(this.id.length - 1);
  //tabID : content1 / content2 / content3
  //tabId = 클릭한 객체의 id에서 맨뒷숫자
  activateTab(this); // 탭 메뉴에 대한 내용
  showTabContent(tabId); //탭 컨텐츠에 대한 내용
}


//문자열 메서드: charAt()

//this.id: this는 현재 객체를 참조하며, id는 그 객체의 속성. 따라서 this.id는 현재 객체의 id 속성에 저장된 문자열을 나타냄.

//this.id.length: this.id 문자열의 길이를 반환. 문자열의 길이는 0부터 시작하므로, 마지막 문자의 인덱스는 length - 1

//this.id.charAt(this.id.length - 1): charAt() 메서드는 주어진 인덱스에 해당하는 문자를 반환. 여기서는 마지막 문자의 인덱스를 사용하여 마지막 문자를 추출


// 초기 탭 설정
activateTab(tabs[0]); // 탭 메뉴
showTabContent('content1'); //탭 컨텐츠

//클릭한 탭 메뉴 배경색상 바꾸기
//클릭한 탭에 대한 처리가 필요. 매개변수로 this로 받아야함.
function activateTab(tab) { //tab : 클릭한 객체 전달, 탭 메뉴 div 데이터가 들어가 있다.
 
  // 모든 탭 비활성화
  var tabs = document.querySelectorAll('.tab');
  for (var i = 0; i < tabs.length; i++) {
    tabs[i].className = 'tab'; // 클래스 이름을 초기화
  }

  // 선택한 탭 활성화
  tab.className = 'tab active'; // active 클래스 추가
}

//모든 탭 내용 숨기고 선택한 탭 내용 표시하기
function showTabContent(tabId) {
  // 모든 탭 내용 숨기기
  var contents = document.querySelectorAll('.tab-content');
  for (var i = 0; i < contents.length; i++) {
    contents[i].style.display = 'none';
    // display 속성으로 숨김
  }

  // 선택한 탭 내용 표시
  var activeContent = document.querySelector("#" + tabId);
  if (activeContent) {
    activeContent.style.display = 'block'; // display 속성으로 표시
  }
}

 

2)

// Step1. 요소 선택하기
var tabs = document.querySelectorAll('.tab');
var contents = document.querySelectorAll('.tab-content');

// Step2. 이벤트 할당하기
for (var i = 0; i < tabs.length; i++) {
  tabs[i].addEventListener('click', tabIdCalculator);
}

// Step3. 함수 선언하기
// Step4. 함수 기능 정의하기
/*
최종 목적 :
 탭메뉴버튼 클릭하면,
 1. 클릭한 탭메뉴 배경 색상 바꾸기
 2. 클릭한 탭메뉴에 해당하는 컨텐츠 나타내기
  2.1 클릭한 탭메뉴(this)와 해당 컨텐츠의 접점 만들기
  2.2 접점 활용하여 컨텐츠 나타내기, 그외 숨김
*/
function tabIdCalculator() {
  var tabId = 'content-' + this.id;
  //content-tab1, content-tab2, content-tab3

  activateTab(this);  
  showTabContent(tabId);
}

function activateTab(tab) {
  //tab = this; 이벤트가 발생한 본인 요소
  for (var i = 0; i < tabs.length; i++) {
    tabs[i].classList.remove('active');
  }
  tab.classList.add('active');
}

function showTabContent(tabId) {
  //tabId : content-tab1, content-tab2, content-tab3
  for (var i = 0; i < contents.length; i++) {
    contents[i].classList.remove('active');
  }

  var activeContent = document.querySelector("#" + tabId);
  if (activeContent) {
    activeContent.classList.add('active');
  }
}

 

 

예제)

 

<html>

<body>
  <section id="menu" class="container">
    <div>
      <h1 class="title">Our Menu</h1>
    </div>
    <div id="tab_box">
      <div id="tab_button">
        <div class="tab" id="a">All</div>
        <div class="tab" id="b">Burger</div>
        <div class="tab" id="c">Pizza</div>
        <div class="tab" id="d">Pasta</div>
        <div class="tab" id="e">Fries</div>
      </div>
      <div id="tab_content">
        <!-- all menu -->
        <!-- div 하나 안에 content 넣기 class 많이 써도 됨-->
       
          <div class="all a card_box">
            <div class="img_box">
              <img src="https://themewagon.github.io/feane/images/f1.png" alt="Pizza">
            </div>
            <div class="text_box">
              <h5>Delicious Pizza</h5>
              <p>Veniam debitis quaerat officiis quasi<br> cupiditate quo, quisquam velit, magnam<br> voluptatem
                repellendus sed eaque</p>
            </div>
            <div class="cart">
              <h6>$20</h6>
              <a href="#"><i class="fa-solid fa-cart-shopping"></i></a>
            </div>
          </div>

          <div class="all a card_box">
            <div class="img_box">
              <img src="https://themewagon.github.io/feane/images/f2.png" alt="Burger">
            </div>
            <div class="text_box">
              <h5>Delicious Burger</h5>
              <p>Veniam debitis quaerat officiis quasi<br> cupiditate quo, quisquam velit, magnam<br> voluptatem
                repellendus sed eaque</p>
            </div>
            <div class="cart">
              <h6>$15</h6>
              <a href="#"><i class="fa-solid fa-cart-shopping"></i></a>
            </div>
          </div>

          <div class="all a card_box">
            <div class="img_box">
              <img src="https://themewagon.github.io/feane/images/f3.png" alt="Pizza">
            </div>
            <div class="text_box">
              <h5>Delicious Pizza</h5>
              <p>Veniam debitis quaerat officiis quasi<br> cupiditate quo, quisquam velit, magnam<br> voluptatem
                repellendus sed eaque</p>
            </div>
            <div class="cart">
              <h6>$17</h6>
              <a href="#"><i class="fa-solid fa-cart-shopping"></i></a>
            </div>
          </div>

          <div class="all a card_box">
            <div class="img_box">
              <img src="https://themewagon.github.io/feane/images/f4.png" alt="Pasta">
            </div>
            <div class="text_box">
              <h5>Delicious Pasta</h5>
              <p>Veniam debitis quaerat officiis quasi<br> cupiditate quo, quisquam velit, magnam<br> voluptatem
                repellendus sed eaque</p>
            </div>
            <div class="cart">
              <h6>$18</h6>
              <a href="#"><i class="fa-solid fa-cart-shopping"></i></a>
            </div>
          </div>

          <div class="all a card_box">
            <div class="img_box">
              <img src="https://themewagon.github.io/feane/images/f5.png" alt="Fries">
            </div>
            <div class="text_box">
              <h5>French Fries</h5>
              <p>Veniam debitis quaerat officiis quasi<br> cupiditate quo, quisquam velit, magnam<br> voluptatem
                repellendus sed eaque</p>
            </div>
            <div class="cart">
              <h6>$10</h6>
              <a href="#"><i class="fa-solid fa-cart-shopping"></i></a>
            </div>
          </div>

          <div class="all a card_box">
            <div class="img_box">
              <img src="https://themewagon.github.io/feane/images/f6.png" alt="Pizza">
            </div>
            <div class="text_box">
              <h5>Delicious Pizza</h5>
              <p>Veniam debitis quaerat officiis quasi<br> cupiditate quo, quisquam velit, magnam<br> voluptatem
                repellendus sed eaque</p>
            </div>
            <div class="cart">
              <h6>$15</h6>
              <a href="#"><i class="fa-solid fa-cart-shopping"></i></a>
            </div>
          </div>

          <div class="all a card_box">
            <div class="img_box">
              <img src="https://themewagon.github.io/feane/images/f7.png" alt="Burger">
            </div>
            <div class="text_box">
              <h5>Tasty Burger</h5>
              <p>Veniam debitis quaerat officiis quasi<br> cupiditate quo, quisquam velit, magnam<br> voluptatem
                repellendus sed eaque</p>
            </div>
            <div class="cart">
              <h6>$12</h6>
              <a href="#"><i class="fa-solid fa-cart-shopping"></i></a>
            </div>
          </div>

          <div class="all a card_box">
            <div class="img_box">
              <img src="https://themewagon.github.io/feane/images/f8.png" alt="Burger">
            </div>
            <div class="text_box">
              <h5>Tasty Burger</h5>
              <p>Veniam debitis quaerat officiis quasi<br> cupiditate quo, quisquam velit, magnam<br> voluptatem
                repellendus sed eaque</p>
            </div>
            <div class="cart">
              <h6>$14</h6>
              <a href="#"><i class="fa-solid fa-cart-shopping"></i></a>
            </div>
          </div>

          <div class="all a card_box">
            <div class="img_box">
              <img src="https://themewagon.github.io/feane/images/f9.png" alt="Pasta">
            </div>
            <div class="text_box">
              <h5>Delicious Pasta</h5>
              <p>Veniam debitis quaerat officiis quasi<br> cupiditate quo, quisquam velit, magnam<br> voluptatem
                repellendus sed eaque</p>
            </div>
            <div class="cart">
              <h6>$10</h6>
              <a href="#"><i class="fa-solid fa-cart-shopping"></i></a>
            </div>
          </div>
       

        <!-- burger menu -->
       
          <div class="all b card_box">
            <div class="img_box">
              <img src="https://themewagon.github.io/feane/images/f2.png" alt="Burger">
            </div>
            <div class="text_box">
              <h5>Delicious Burger</h5>
              <p>Veniam debitis quaerat officiis quasi<br> cupiditate quo, quisquam velit, magnam<br> voluptatem
                repellendus sed eaque</p>
            </div>
            <div class="cart">
              <h6>$15</h6>
              <a href="#"><i class="fa-solid fa-cart-shopping"></i></a>
            </div>
          </div>

          <div class="all b card_box">
            <div class="img_box">
              <img src="https://themewagon.github.io/feane/images/f7.png" alt="Burger">
            </div>
            <div class="text_box">
              <h5>Tasty Burger</h5>
              <p>Veniam debitis quaerat officiis quasi<br> cupiditate quo, quisquam velit, magnam<br> voluptatem
                repellendus sed eaque</p>
            </div>
            <div class="cart">
              <h6>$12</h6>
              <a href="#"><i class="fa-solid fa-cart-shopping"></i></a>
            </div>
          </div>

          <div class="all b card_box">
            <div class="img_box">
              <img src="https://themewagon.github.io/feane/images/f8.png" alt="Burger">
            </div>
            <div class="text_box">
              <h5>Tasty Burger</h5>
              <p>Veniam debitis quaerat officiis quasi<br> cupiditate quo, quisquam velit, magnam<br> voluptatem
                repellendus sed eaque</p>
            </div>
            <div class="cart">
              <h6>$14</h6>
              <a href="#"><i class="fa-solid fa-cart-shopping"></i></a>
            </div>
          </div>
       

        <!-- pizza menu -->
          <div class="all c card_box">
            <div class="img_box">
              <img src="https://themewagon.github.io/feane/images/f1.png" alt="Pizza">
            </div>
            <div class="text_box">
              <h5>Delicious Pizza</h5>
              <p>Veniam debitis quaerat officiis quasi<br> cupiditate quo, quisquam velit, magnam<br> voluptatem
                repellendus sed eaque</p>
            </div>
            <div class="cart">
              <h6>$20</h6>
              <a href="#"><i class="fa-solid fa-cart-shopping"></i></a>
            </div>
          </div>

          <div class="all c card_box">
            <div class="img_box">
              <img src="https://themewagon.github.io/feane/images/f3.png" alt="Pizza">
            </div>
            <div class="text_box">
              <h5>Delicious Pizza</h5>
              <p>Veniam debitis quaerat officiis quasi<br> cupiditate quo, quisquam velit, magnam<br> voluptatem
                repellendus sed eaque</p>
            </div>
            <div class="cart">
              <h6>$17</h6>
              <a href="#"><i class="fa-solid fa-cart-shopping"></i></a>
            </div>
          </div>

          <div class="all c card_box">
            <div class="img_box">
              <img src="https://themewagon.github.io/feane/images/f6.png" alt="Pizza">
            </div>
            <div class="text_box">
              <h5>Delicious Pizza</h5>
              <p>Veniam debitis quaerat officiis quasi<br> cupiditate quo, quisquam velit, magnam<br> voluptatem
                repellendus sed eaque</p>
            </div>
            <div class="cart">
              <h6>$15</h6>
              <a href="#"><i class="fa-solid fa-cart-shopping"></i></a>
            </div>
          </div>
       

        <!-- pasta menu -->
          <div class="all d card_box">
            <div class="img_box">
              <img src="https://themewagon.github.io/feane/images/f4.png" alt="Pasta">
            </div>
            <div class="text_box">
              <h5>Delicious Pasta</h5>
              <p>Veniam debitis quaerat officiis quasi<br> cupiditate quo, quisquam velit, magnam<br> voluptatem
                repellendus sed eaque</p>
            </div>
            <div class="cart">
              <h6>$18</h6>
              <a href="#"><i class="fa-solid fa-cart-shopping"></i></a>
            </div>
          </div>

          <div class="all d card_box">
            <div class="img_box">
              <img src="https://themewagon.github.io/feane/images/f9.png" alt="Pasta">
            </div>
            <div class="text_box">
              <h5>Delicious Pasta</h5>
              <p>Veniam debitis quaerat officiis quasi<br> cupiditate quo, quisquam velit, magnam<br> voluptatem
                repellendus sed eaque</p>
            </div>
            <div class="cart">
              <h6>$10</h6>
              <a href="#"><i class="fa-solid fa-cart-shopping"></i></a>
            </div>
          </div>
       
        <!-- fries menu -->
          <div class="all e card_box">
            <div class="img_box">
              <img src="https://themewagon.github.io/feane/images/f5.png" alt="Fries">
            </div>
            <div class="text_box">
              <h5>French Fries</h5>
              <p>Veniam debitis quaerat officiis quasi<br> cupiditate quo, quisquam velit, magnam<br> voluptatem
                repellendus sed eaque</p>
            </div>
            <div class="cart">
              <h6>$10</h6>
              <a href="#"><i class="fa-solid fa-cart-shopping"></i></a>
            </div>
          </div>
       
      </div>
    </div>
    <div class="view_button"><a href="#">View More</a></div>
  </section>
</body>

 

<css>

*{
  margin:0;
  padding:0;
  text-decoration : none;
  list-style:none;
  box-sizing:border-box;
  color: inherit;
}

.container{
  width: 70%;
  margin: 0 auto;
}
 
#menu .title{
  text-align: center;
  font-size: 35px;
  margin-top: 30px;
  font-family: "Dancing Script", cursive;
  font-optical-sizing: auto;
  font-weight: 600;
  font-style: normal;
  margin-bottom: 30px;
}

#tab_button{
 display: flex;
 justify-content: center;
 align-items: center;
 margin-bottom: 20px;
}

.tab{
  margin-right: 50px;
  padding: 10px;
  font-family: "Open Sans", sans-serif;
}

#menu #tab_content {
  display: flex;
  flex-wrap: wrap;
  margin-bottom: 20px;
  /* justify-content: center;
  /* align-items: center; */  /* 배열 달라짐 */
}

#menu .card_box{
  width:30%;
  height: 100%;
  /* border: 3px solid red; */
  margin: 20px;
  /* transition: all 1s; ->display: none; 일 때 효과 안먹힘 opacity, scale, height주기
     투명도로 해두면 그 자리에 그대로 남아 있어서 보이지 않을 뿐 위치해 있음, position으로 위치 조정 해주어야 함*/
  background-color: #0c0c0c;
  border-radius: 30px;
  /* overflow: hidden; */
}

/* 배경 주고 반지름 주기 */

.img_box{
  width: 100%;
  height: 200px;
  padding-left: 50px;
  padding-right: 50px;
  background-color: #f1f2f3;
  border-radius: 20px 20px 0 20px;
}

.img_box img{
  width: 100%;
  height: 200px;
  padding: 20px;
}

.text_box{
  width: 100%;
  padding: 15px;
  /* background-color: #0c0c0c; */
  color: #ffffff;
  /* border: 3px solid blue; */
}

.text_box h5{
  font-size: 20px;
  font-family: "Open Sans", sans-serif;
  margin-top: 10px;
  margin-bottom: 10px;
}

.text_box p, h6{
  font-family: "Open Sans", sans-serif;
  font-size: 15px;
}

.cart{
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 15px;
  /* background-color: #0c0c0c; */
  color: #ffffff;
  border-radius: 0 0 20px 20px;
}

.cart a{
  display: inline-block;
  width: 40px;
  height: 40px;
  line-height: 40px;
  text-align: center;
  border-radius: 30px;
  background-color: #ffbe33;
}


.all{
 display: none;
 /* opacity: 0; */
}

/* #a, #b, #c, #d, #e{
  display: none;
} */

/* 버튼 추가 */

.view_button {
  text-align: center;
}

.view_button a{
  display: inline-block;
  border: 1px solid;
  margin-bottom: 30px;
  padding: 10px 50px;
  border-radius: 30px;
  background-color: #ffbe33;
  color: #ffffff;
  transition: all 0.3s;
}

.view_button a:hover{
  background-color: #fd7e14;
}


.tab-content{
  /* display: none; */
  padding: 20px;
  border: 1px solid #ccc;
}

.tab.active {
  background-color: #ccc;
}

.all.active{
  display: block;
}

 

<js>

//1.셀렉트 하가
let tabs = document.querySelectorAll('.tab');

//2.이벤트 할당하기
for(let i = 0; i < tabs.length; i++) {
  tabs[i].addEventListener('click', tabIdCalculator);
} //텝메뉴

//텝메뉴-텝컨텐츠 연결: id 속성
function tabIdCalculator() {
  let tabId = this.id;
  activateTab(this);
  showTabContent(tabId);
}

activateTab(tabs[0]); // 탭 메뉴
showTabContent('a'); //탭 컨텐츠

// function activateTab(tab) {
//   // 모든 탭 비활성화
//   let tabs = document.querySelectorAll('.tab');
//   for (let i = 0; i < tabs.length; i++) {
//     tabs[i].classList.remove("active");
//   }

//   // 선택한 탭 활성화
//   tab.classList.add("active");
// }

function activateTab(tab) {
  // 모든 탭 비활성화
  let tabs = document.querySelectorAll('.tab');
  for (let i = 0; i < tabs.length; i++) {
    tabs[i].className = 'tab'; // 클래스 이름을 초기화
  }

  // 선택한 탭 활성화
  tab.className = 'tab active'; // active 클래스 추가
  console.log(tab.className);
}


function showTabContent(tabId) {
  let contents = document.querySelectorAll('.all');
  for(let i = 0; i<contents.length; i++) {
    contents[i].style.display = 'none';
  }

  console.log(tabId);
  let activeContents = document.querySelectorAll("." + tabId);
  console.log("length : "+activeContents.length);
  if(activeContents.length != 0) {
    activeContents.forEach(function(activeContent){
      activeContent.style.display = 'block';
    });
  }
}