ANDAR Mobile 클론코딩

핑구·2023년 7월 21일
0

Portfolio

목록 보기
2/5

🏃‍♀️ ANDAR Mobile

👉 사이트명 : 안다르 모바일
👉 작업기간 : 2일 ( 23.07.13. ~ 07.14. )
👉 사용언어 : HTML5, CSS3, Jquery
👉 라이브러리 : Swiper.js
👉 분류 : 모바일 적응형 웹사이트
👉 URL : https://seona-cha.github.io/andar/


POINT ✨

✔️ HEADER (스크롤시 효과)
✔️ SVG 사용 - 하나의 파일로 색 변경 효과주기
✔️ GNB 열림 - 바깥영역 클릭시 닫힘
✔️ 비주얼 슬라이더의 height값을 calc()로 계산해서 상하단 여백 보장
✔️ 겹치는 공통 클래스로 컨트롤
✔️ A태그 위에 A태그 띄우기

구조 살펴보기 👀

🔍 전체 태그를 wrapper로 감싸주기 (적응형)
🔍 시멘틱 태그를 활용해 영역 구성
🔍 각각의 section에는 h2태그로 제목 구성
🔍 클래스명에 통일성을 주어 직관적으로 구조를 파악할수있도록 구성


📍 HEADER

기존 헤더개선 헤더

안다르 모바일 헤더는 스크롤을 내리면 헤더의 배경색이 변하면서 페이지 최상단에 고정되고, 다시 스크롤이 올라가면 원래 자리로 돌아간다.

기존 안다르 모바일 홈페이지는 1px이라도 스크롤되면 바로 헤더가 상단에 붙는데,
이 부분을 좀더 자연스럽게 만들고 싶어서 나는 헤더의 위치까지 스크롤이 될 경우에 붙도록 만들었다.

$(window).scroll(function(){
  curr = $(this).scrollTop(); // 현재 위치 값을 불러옴
  target = $('.header').offset().top; // .header의 상단 위치 값을 불러옴
  if(curr >= target){
    $('.header').addClass('fixed');
    $('.header path').css("fill","#000");
  }else{
    $('.header').removeClass('fixed');
    $('.header path').css("fill","#fff");
  }
})

📍 SVG 사용 - 하나의 파일로 색 변경 효과주기

위와 같이 스크롤시 색이 변하는 헤더를 만들 때 SVG를 사용하면 효율적이다!

PNG, GIF등의 포맷을 사용할 경우

👎 각각 흰색, 검정색의 2가지 파일이 필요
👎 서버에 파일을 두번 요청해야해서 효율적이지 못함

SVG를 사용할 경우

👍 파일 하나로 CSS를 이용해 색상을 다양하게 변경 가능
👍 벡터 방식이라 사이즈를 조정해도 해상도가 깨지지 않음


👀 안다르 모바일 사이트에서는 파일 형식 자체는 SVG를 이용했지만, black 버전과 white 버전을 각각 따로 업로드하여 사용 중인데 ~ 나는 이 부분을 좀더 효율적으로 만들기 위해 하나의 파일만 사용했다. 💁‍♀️

👉 SVG태그를 이용하여 파일을 업로드

<h1 class="logo">
  <a href="#">
    <span class="blind">ANDAR</span>
    <svg width='87' height='24' viewBox='0 0 80 21' preserveAspectRatio="none" fill='#fff' xmlns='. . '>
      <path fill-rule='evenodd' clip-rule='. . .' fill='#fff'/><!-- Code injected by live-server -->
    </svg>
  </a>
</h1>

( preserveAspectRatio="none" 는 가로세로 비율을 보존하지 않고 강제로 사이즈를 맞출때 사용)

👉 ScorllTop 값이 헤더 상단부분보다 커질경우, fill값을 바꿔서 색이 바뀌도록 처리

$(window).scroll(function(){
  curr = $(this).scrollTop();
  target = $('.header').offset().top;
  if(curr >= target){
    $('.header').addClass('fixed');
    $('.header path').css("fill","#000"); //fill 값 조정
  }else{
    $('.header').removeClass('fixed');
    $('.header path').css("fill","#fff"); //fill 값 조정
  }
})

📍 HEADER 내부 NAV 토글

👉 header 영역에 카테고리 메뉴 열고 닫는 부분은 토글 버튼으로 구성했다.
👉 스크린 리더 사용자를 위해 aria-label의 내용도 바뀌도록 만들기 !

① 메뉴 토글, CSS 변경은 slideToggle(), toggleClass() 메서드로 구성

$('.allmenu-toggle.open').click(function(){
  $(this).toggleClass('open').toggleClass('close');
  $('.allmenu-title').toggleClass('on');
  $('.allmenu-area').stop().slideToggle();
	.
    .
})

② aria-label은 조건문을 이용

$('.allmenu-toggle.open').click(function(){
  .
  .
  if($(this).attr('aria-label') == '메뉴열기'){
    $(this).attr('aria-label','메뉴닫기')
    
  }else if($(this).attr('aria-label') == '메뉴닫기'){
    $(this).attr('aria-label','메뉴열기')
  }
})

📍 GNB, SEARCH 버튼 클릭시 각 영역 보여주기

// GNB 열고닫기
$('.gnb-btn').click(function(){
    $('body').addClass('dimmed');
    $('.gnb').addClass('on');
})
$('.gnb-close').click(function(){
    $('body').removeClass('dimmed');
    $('.gnb').removeClass('on');
})

💡 메뉴/검색영역이 열릴때는 body에 'dimmed' 클래스를 추가해 아래와 같이 활용했다.

① 메뉴가 열렸을때 페이지가 스크롤 되지 않도록 처리하기

body.dimmed{
    height: 100%;
    overflow: hidden;
}

② 바깥 영역 어둡게 처리하기

body.dimmed:after{
    display: block;
    position: fixed;
    top: 0;left: 0;
    width: 100%;
    height:100%;
    background: rgba(0,0,0,0.65);
    z-index:11;
    content:'';
    opacity: 1;
    transition: opacity 0.5s;
}

📍 GNB 영역의 바깥부분을 누르면 닫히도록 구성

$(document).click(function(e){
  if($('.gnb').hasClass('on')){ //메뉴가 열렸을 때 동작
    if(
      $('.gnb').has(e.target).length == 0 && // .gnb에 사용자가 클릭한 요소가 포함
      $('.gnb-btn').has(e.target).length == 0 // .gnb-btn에 사용자가 클릭한 요소가 포함
    ){
      $('body').removeClass('dimmed');
      $('.gnb').removeClass('on');
    }
  }
})

💣 스크립트를 작성하는 중 조건문에 $('.gnb').has(e.target).length == 0 만 사용했더니,

① GNB 버튼을 누를때부터 .gnb에 'on'클래스가 생기고,
② GNB버튼이 gnb영역 바깥에 있기때문에 동작하지 않음

👉 그래서 && $('.gnb-btn').has(e.target).length == 0를 추가해주었다.


📍 Visual 영역 - height: calc()

height 값이 바뀌어도 상단 배너와 아래 영역 100px 되는 부분을 보장하기 위해 calc()를 사용했다.
그리고 img태그일 경우 object-fit:cover를 이용하면, background-size:cover와 같은 느낌으로 가로세로 비율이 안맞아도 이미지를 강제로 늘리지 않고 맞춰 잘라준다.

.sc-visual img{
  width: 100%;
  height: calc(100vh - 141px);
  object-fit: cover;
}

📍 공통 클래스

✔️ 레이아웃이 공통되는 부분은 같은 클래스를 주어 효율적인 CSS 작성
✔️ 차이점이 있는 부분은 다른 클래스로 컨트롤해서 구성해주었다.

예시 - 공통 레이아웃은 sc-banner 클래스, 배경 부분이 달라서 각각 membership, store 클래스로 조정함

<section class="sc-banner membership">
  <a href="#">
    <h2 class="title">안다르 멤버십</h2>
    <p class="desc">5,000원 쿠폰 지급, 상시 5% 할인<br>등급별 혜택을 놓치지마세요.</p>
    <span class="banner-more">자세히 보기</span>
  </a>
</section>

<section class="sc-banner store">
  <a href="#">
    <div class="title">안다르 오프라인 스토어 안내</div>
    <p class="desc">
      전국 백화점과 아울렛에서 안다르 제품을 경험하세요.<br>
      안다르만의 스토어 멤버십을 통해<br>
      특별한 혜택도 함께 누려보세요.
    </p>
    <span class="banner-more">자세히 보기</span>
  </a>
</section>

📍 상품 영역 링크 처리

👉 각 아이템의 전체 영역은 해당 상품의 링크로 이동
👉 리뷰 부분을 누르면 해당 상품의 리뷰 목록 링크로 이동

이렇게 기획되었다고 가정하고 작업

그런데 마크업 시 a태그 안에 a태그를 사용하는 것은 문법상 맞지 않아서 다른 방법을 택했다.

① 아이템 정보영역이 시작되는 최상단에 전체 영역 링크를 따로 빼 준다.

리뷰 링크는 기존 방식 그대로 작성했다.

<ul class="grid-list prd">
  <li class="grid-item">
    <a href="#"></a> <!--상품 전체영역 링크-->
    <div class="img-box">
      <img src="./assets/images/best_2.jpg" alt>
    </div>
    <div class="product-info">
      <span class="review"><a href="#">리뷰 131,739</a></span> <!--리뷰영역은 노멀-->
      <strong>[1+1] 에어쿨링 지니 시그니처 레깅스</strong>
      <div class="price">
        <em class="discount">50%</em>49,000원<del>98,000원</del>
      </div>
      <span class="label">애슬레저 1위</span>
    </div>
  </li>
  .
  .
</ul>

② 전체 링크 영역의 위치와 크기를 잡아준다.

position:absolute로 위치를 잡아주고, display:block; 처리 후 너비와 높이를 잡아준다.

.prd li > a{
  position:absolute;
  z-index:1;
  width: 100%;
}
.grid-item > a {
  height: calc(100% - 50px);
}

③ 리뷰 부분의 링크를 z-index로 윗쪽으로 띄워준다.

.product-info .review{
  position: relative;
  z-index:2;
  .
  .
}

📍 BEST 영역 - Tab Menu

① HTML - 탭 메뉴 구성

👉 탭 메뉴 버튼의 data-tab 속성과 탭 컨텐츠의 id값을 맞춰주었다.

<ul class="tab-list">
  <li class="tab-item on"><a href="#" data-tab="#tabcon1">전체</a></li>
  <li class="tab-item"><a href="#" data-tab="#tabcon2">우먼즈</a></li>
</ul>

<div class="tabcon on" id="tabcon1">
.
.
</div>
<div class="tabcon" id="tabcon2">
.
.
</div>

② CSS -'on' 클래스 추가시 제어할 부분

/* 메뉴버튼 on시 배경색, 텍스트 색 변경 */
.sc-best .tab-item.on{
  background: #b7561f;
  font-weight: 600;
  color: #fff;
}
/*탭 컨텐츠 display 속성 제어*/
.sc-best .tabcon{
    display:none;
}
.sc-best .tabcon.on{
    display: block;
}

③ Script - 탭 버튼 클릭시

$('.tab-item').click(function(e){
    e.preventDefault(); // a태그 동작으로 페이지가 새로고침되지 않도록
    tabCon = $(this).children().data('tab'); // 자식요소인 a의 data-tab을 참조해 변수에 담기
	
    $(this).addClass('on').siblings().removeClass('on'); // 메뉴버튼 CSS 컨트롤을 위함
    $(tabCon).addClass('on').siblings().removeClass('on'); // 컨텐츠 display 제어
})

📍 Quick Menu

👉 스크롤을 아래로 내릴때 사라지고,
👉 위로 스크롤시 나타나도록 작업

💎 퀵메뉴 나타나기/사라지기

let lastScroll = 0; // 직전 스크롤값을 담을 변수

$(window).scroll(function(){
  curr = $(this).scrollTop(); // 현재 스크롤값
  if(curr < lastScroll){ //현재 스크롤값이 직전 스크롤값보다 작을경우
    $('.quick-menu').addClass('on');
  } else {
    $('.quick-menu').removeClass('on');
  }
  lastScroll = curr; //조건문 실행이후 변수에 현재 스크롤값 저장 
})

💎 맨 위로 버튼

$('.top-btn').click(function(){
    window.scrollTo({
        top:0,
        behavior:"smooth"
    })
})

profile
배운것은 그날그날 잊지않고 기록하기

0개의 댓글