[클론코딩] ANDAR

J.yeon·2024년 1월 12일
0
post-thumbnail

프로젝트👩‍💻 : ANDAR
사용언어🛠️ : HTML5, CSS3, JAVASCRIPT
라이브러리📁 : jQuery, Swiper
타입⚙️ : 적응형 Mobile
⏱️ : 3일 소요


✅ W3C Markup · CSS3 Pass


📌<h>태그 outline📌


✨KEY POINT

  • 사이드gnb의 dimmed를 활용한 닫기
  • 다양한 swiper와 swiper effect
  • dataset을 이용한 tab 구현
  • css counter 자동 순위
  • 공통 style class
  • 웹표준을 준수한 link처리



사이드gnb의 dimmed를 활용한 닫기

gnb가 열리면 body에 hidden클래스가 붙도록 했습니다.
✨이때 클래스가 붙으면 가상선택자에 dimmed가 형성되게끔 하여 불필요한 코드를 줄였습니다.

body.hidden {
    overflow: hidden;
}

/* dimmed */
body.hidden::after {
    content: '';
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: rgba(0, 0, 0, 0.5);
    z-index: 55;
}

하지만 이럴 경우, dimmed를 클릭하여 gnb를 닫을 때 조금 까다로울 수 있습니다.

가상선택자는 스크립트로 조절이 어렵기때문에 그 부모인 body를 클릭하여 gnb를 닫아야하는데,
body자체에 클릭이벤트를 주게되면 gnb자체가 열리기도 전에 닫히는 상태가 되어버립니다.

// 잘못된 코드❌
$('body').click(function () {
    $('.gnb').removeClass('on');
    $('body').removeClass('hidden');
});

✨이같은 문제에선 click 이벤트의 e.target 을 이용하여 해결했습니다.

// 해결 코드⭕
$(document).click(function (e) {
    if ($('.wrapper').has(e.target).length === 0) {
        $('.gnb').removeClass('on');
        $('body').removeClass('hidden');
    }
});

gnb가 열린 상태에서 gnb안쪽을 클릭하면 e.target은 gnb 또는 gnb내부 요소지만,
dimmed를 클릭하면 e.target은 body가 됩니다.

해당 조건을 사용하여 wrapper 안에 body가 존재하지 않는다면 gnb가 닫히도록 구현했습니다.




다양한 swiper와 swiper effect

안다르 클론코딩을 하면서 총 6개의 영역에 swiper를 사용하였습니다.

✨최상단 검정배너와 메인 비주얼 슬라이드에는 swiper effectfade 를 넣었습니다.

// 최상단 배너
const MainTopSwiper = new Swiper('.top-banner', {
    effect: 'fade', 👈
    loop: true,
    autoplay: {
        delay: 4000,
        disableOnInteraction: false,
    },
});

// 메인 비주얼 슬라이드
const MainVisual = new Swiper('.sc-visual .swiper', {
    effect: 'fade', 👈
    loop: true,
    pagination: {
        el: '.pagination',
    },
    autoplay: {
        delay: 4000,
        disableOnInteraction: false,
    },
});

✨마지막 swiper인 레깅스가 포함된 section.sc-cate 에는 동일한 구조의 swiper 3개가 있기때문에,
클래스 group-cate 로 동일한 스타일을 주고 swiper도 동일하게 적용했습니다.

동일한 클래스에 동일한 swiper 구조이기때문에 반복문없이 사용 가능했습니다.

<section class="sc-cate">
    <div class="group-cate leggings">
        <!-- 동일한 swiper 구조 -->
    </div>
    <div class="group-cate bratop">
        <!-- 동일한 swiper 구조 -->
    </div>
    <div class="group-cate set">
        <!-- 동일한 swiper 구조 -->
    </div>
</section>
// 카테고리별 상품 슬라이드
const cateSwiper = new Swiper('.sc-cate .swiper', {
    slidesPerView: 2.1,
    spaceBetween: 10,
    freeMode: true,
});



dataset을 이용한 tab 구현

section.sc-best탭 영역입니다.
✨먼저 role 속성으로 탭역할을 알려줘 접근성을 올려주었습니다.

이후 코드를 좀더 간결하고 쉽게 사용하기위해 dataset 을 사용했습니다.

<section class="sc-best">
  //탭 메뉴
  <ul class="tab-list" role="tablist">
    <li class="tab-item" data-tab=".tabcon1" role="tab">메뉴1</li>
    <li class="tab-item" data-tab=".tabcon2" role="tab">메뉴2</li>
  </ul>
  
  //탭 내용(패널)
  <ul class="tabcon-list">
    <li class="tabcon-item tabcon1" role="tabpanel">내용1</li>
    <li class="tabcon-item tabcon2" role="tabpanel">내용2</li>
  </ul>
</section>

✨탭메뉴에 data-tab 으로 패널의 클래스네임과 동일한 값을 넣어주어
클릭한 메뉴의 data값을 불러와 변수로 담고, 그 변수를 선택자로 사용하였습니다.

$('.sc-best .tab-item').click(function (e) {
    e.preventDefault();
    tabName = $(this).data('tab'); 👈

    $(this).addClass('on').siblings().removeClass('on');
    $(tabName).addClass('on').siblings().removeClass('on'); 👈
});



css counter 자동 순위

안다르 클론코딩을 하면서 Counter 라는 css 기능을 알게되어 활용해보았습니다.

Counter란?
문서 내에서 특정 요소의 순서를 추적하고 그 값을 스타일에 적용하는 CSS 기능으로,
counter-reset 및 counter-increment 속성을 사용하여 카운터를 초기화하고 증가시킬 수 있다.
이를 활용하여 목록 아이템에 번호를 자동으로 할당하거나 특정 요소에 고유한 식별자를 부여할 수 있다.

🍏모든 브라우저에서 사용 가능
🔗Counter

안다르 콘텐츠 중 BEST 영역에는 제품마다 번호가 쓰여져 있습니다.

before로 표현해도 되겠다싶어 처음에는 각 li마다 하나씩 입력해주는 방식으로 코드를 짰습니다.

ul > li:nth-child(1)::before {
	content: '1';
}
ul > li:nth-child(2)::before {
	content: '2';
}
ul > li:nth-child(3)::before {
	content: '3';
}
ul > li:nth-child(4)::before {
	content: '4';
}
/* --- 이하 생략 */

하지만 위처럼 코드가 너무 길어지고, 데이터 변환시에는 list의 순서도 바뀌는 문제가 있다고 판단해 좀더 효율적인 방법을 찾아 해결했습니다.

✨Counter 사용으로 li 순서에 따라 번호가 자동으로 할당되게 했습니다.
또한 li의 데이터가 사라지거나 위치가 변경되어도 그에 따라 번호가 다시 순서대로 재할당됩니다.

ul {
	/* 초기 카운터 값 설정(기본 0) */
    counter-reset: name;
}
ul > li::before {
	/* 카운터 값 증가 */
    counter-increment: name;
    /* 번호 표시 */
    content: counter(name);
}



공통 style class

안다르 클론코딩을 하면서 비슷한 구조와 스타일이 많이 중복되는 것을 알 수 있었습니다.
특히, 제품 list의 구성은 이미지와 텍스트로 이루어져있어 공통 스타일로 묶기 용이했습니다.

.img-box.txt-box 로 공통 클래스를 구분하여 작업해 코드를 줄이고 제작 시간을 단축시켰습니다.

/* ---상품 정보 공통ul */
.img-box {
    position: relative;
}
.img-box img {
    width: 100%;
}
.img-box .ico {
    position: absolute;
    top: 0;
    right: 0;
    width: 16%;
    min-width: 38px;
}
.txt-box {
    display: flex;
    flex-direction: column;
    align-items: start;
    gap: 10px;
    padding: 15px 5% 0;
}
.txt-box .review {
    font-size: 13px;
    font-weight: 600;
    line-height: 1;
    color: #8e1f29;
}
.txt-box .title {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    text-overflow: ellipsis;
    overflow: hidden;
    font-size: 14px;
    line-height: 17px;
    letter-spacing: -0.05em;
}

	/* 이하 생략 */
    
/* ---//상품 정보 공통ul */



웹표준을 준수한 link처리

다른 콘텐츠와 마찬가지로 영상이 포함된 콘텐츠도 클릭시 링크이동이 되어야 합니다.

iframea 태그로 감싸는 형태는 웹표준에 적합한 코드가 아니기때문에 해당 부분만 따로 수정해주었습니다.


//수정 전 [❌]
<section class="group-recomm">
    <a href="#">
        <div class="img-box">
        	<iframe src="영상링크"></iframe>
        </div>
    </a>
</section>
//수정 후 [⭕]
<section class="group-recomm">
    <div class="relative">
        <a href="#" class="link-cover"></a>
        <div class="img-box">
        	<iframe src="영상링크"></iframe>
        </div>
    </div>
</section>
.link-cover {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
}

💡a 태그 내부에 iframe 태그를 직접 포함하는 것은 일반적으로 허용되지 않습니다.
이러한 제한은 보안 및 웹페이지 구조의 논리성과 일관성을 유지하기 위한 것입니다. 만약 하이퍼링크를 통해 외부 페이지를 로딩하고 동시에 이 페이지 안에 다른 외부 페이지를 iframe으로 불러올 수 있다면, 사용자 경험이 혼란스러워질 수 있고, 보안상의 이슈도 발생할 수 있습니다.

profile
개블리셔 꿈꾸는 퍼블의 개발공부🚶‍♀️ 천천히 걸어가는 중

0개의 댓글

관련 채용 정보