1-1) 자바스크립트 클릭 이벤트
1-2) json 활용 비동기통신
2-1) 쇼핑몰 리스트 html 마크업
2-2) sticky nav(header) css
2-3) fixed top btn
2-4) css gradient
2-5) 공통 scss 정리
2-6) 추후 미디어쿼리 적용
0. 각 클래스 요소 변수 처리
1. btn-search 클릭 시 .search-wrap display:block;
2. btn-close 클릭 시 .search-wrap display:none;
j-query
$('.search-btn').click(function(){
$('.search-wrap').css('display','block');
});
$('.btn-close').click(function(){
$('.search-wrap').css('display','none');
});
java-script
const btnSearach = document.querySelector('.btn-search');
const searchWrap = document.querySelector('.search-wrap');
const btnClose = document.querySelector('.btn-close');
btnSearch.addEventListener('click',()=>{
searchWrap.style.display = 'block';
});
btnClose.addEventListener('click',()=>{
searchWrap.style.display = 'none';
});
*()=>{} == function(){}
비동기처리 기본원리
- json 파일 데이터
{ "member":[ { "이름":"유미", "나이":"18" }, { "이름":"수미", "나이":"28" }, { "이름":"혜미", "나이":"38" } ] }
- java script
fetch("./sample.json") // json파일 불러오기 .then((response) => response.json()) .then((json) => { const member = json.member // json데이터에 member 접근 let html = ''; // 변수가 반복해서 계속들어갈꺼라 한번 생성 member.forEach(el => { // 개수만큼 반복해야함 isAdult = el.나이 < 20 ? '미성년자' : '성인' // 조건문을 통한 정보 분류. json데이터의 나이에 접근하여 나이의 값이 20미만이면 '미성년자', 아니면 '성인' html+=`<li>이름:${el.이름}<br>성인:${isAdult}</li>` // 빈 칸 생성한 변수에 들어갈 html 코드입력 }); const list1 = document.querySelector('.list');// .list 선택 변수 정의 list1.innerHTML = html; // .list에 html 삽입
결과
나는 데이터 비동기처리를 메인 슬라이드 배너와 첫번째 리스트 레이아웃에 적용해보았다.
결과
하지만 여기서 한가지 문제점이 발생하게 되는데... swiper slide loop가 안먹는다!
해결법 -> swiper code를 fetch문 맨 마지막에 넣어서 비동기 -> 스와이퍼 순서로 코딩하면 loop 문제 해결!!!
fetch("./asset/data/mainslide.json")
.then((response) => response.json())
.then((json) => {
const mainSlide = json.mainSlide;
let html = '';
mainSlide.forEach(el => {
html += `<div class="swiper-slide">
<a href="${el.url}">
<img src="${el.imgSrc}" alt="${el.alt}">
</a>
</div>`
});
const slideList = document.querySelector('.sc-visual .swiper-wrapper');
slideList.innerHTML = html;
// 3. sc-visual swiper slide
const slide1 = new Swiper(".slide1 .swiper", {
loop: true,
autoplay: {
delay: 2000,
disableOnInteraction: false,
},
pagination: {
el: ".pagination",
clickable: true,
},
navigation: {
nextEl: ".next",
prevEl: ".prev",
},
});
});
살짝 아쉬운.. 실수한 마크업
1. li > a로 이미지와 정보를 전부 감싼 것
2. 장바구니 추가 버튼을 span태그로 구현한 것
3. 리스트에서 중요한 내용(강조할 내용)을 강조하지 못한 마크업
4. 굳이 h2를 blind처리한 것
5. 광범위한 클래스명
=> 전체적으로 과한 마크업과 정작 중요한 정보는 강조가 안되어 있음
<section class="sc-type2">
<h2 class="blind">샐러드</h2>
<div class="text-box">
<strong class="title">
쓴맛 없고 싱싱한 샐러드
<i class="ic-title greenlove"></i>
</strong>
<p class="desc">건강하고 가볍게 식단 챙겨요</p>
</div>
<div class="group-flex5">
<ul class="product-list">
<li class="product-item">
<a href="#">
<div class="thumb-box">
<img src="./asset/images/salad-thumb1.png" alt="다노 그린믹스샐러드 / 파프리카믹스샐러드">
<div class="badge-box">
<span class="sale">sale</span>
</div>
<span class="cart"><span class="blind">장바구니 추가</span></span>
<div class="info-box">
<em class="free-delivery">무료배송</em>
<span class="product-name">다노 그린믹스샐러드 / 파프리카믹스샐러드</span>
<em class="current-sale">
11%<del>18,900</del>
</em>
<span class="price">
<span>16,900</span>원
</span>
</div>
</a>
</li>
</ul>
</section>
개선 마크업
1. a는 .thumb-box img, .info-box에 각각 감싸서 코딩
2. 장바구니 추가버튼 button으로 변경
3. h2 blind없애고 해당 제목 영역으로 수정
4. 가격,세일은 강조되는 태그 요소로 구성
6. 애매한 클래스명은 의미가 분명하게 수정 (.text-box -> .title-box)
<section class="sc-type2">
<div class="title-box">
<h2 class="title">쓴맛 없고 싱싱한 샐러드<img src="./asset/images/greenlove.png" alt="초록하트아이폰이모지"></i></h2>
<p class="desc">건강하고 가볍게 식단 챙겨요</p>
</div>
<div class="group-flex3">
<ul class="product-list">
<li class="product-item">
<div class="thumb-box">
<a href="#"><img src="./asset/images/salad-thumb1.png" alt="다노 그린믹스샐러드 / 파프리카믹스샐러드"></a>
<div class="badge-box">
<span class="sale">sale</span>
</div>
<button class="cart"><span class="blind">장바구니 추가</span><svg></svg>
</button>
</div>
<a href="#" class="info-box">
<em class="free-delivery"><svg></svg>무료배송</em>
<p class="product-name">다노 그린믹스샐러드 / 파프리카믹스샐러드</p>
<em class="current-sale">11%<del>18,900</del></em>
<span class="price">
<em>16,900</em>원
</span>
</a>
</li>
</section>
sticky란? 스크롤하지 않을 때는 static position처럼 동작하다가 스크롤할 때는 fixed position과 유사하게 동작한다.
Sticky 속성은 Sticky 포지션을 사용할 요소에 Position:sticky; 로 포지션을 지정 후 top:0; 와 같이 고정될 영역만 입력해주면 된다.
-Sticky가 동작 하지 않을 때 확인 사항
1.Sticky 속성을 갖는 요소는 자신의 부모 요소안에서만 적용
2.부모요소중에 overflow:auto, overflow:hidden, overflow:scroll속성이 적용되어 있는 경우 사용 불가
3.IE(Internet Explorer) 사용 불가
sticky를 적용하기 위해서는 left,right,bottom,right의 위치값이 필수이며, height값이 존재해야한다.
다노샵은 모바일 first 웹사이트이기 때문에, .wrapper에 max-width가 존재한다. 그러나 fixed가 되어야하는 top버튼의 기준점은 뷰포트가 되기 때문에, 시안과 동일하게 해당 640px안에 fixed 시키는 것이 어려웠었다.
max-width안에 fixed 처리하는 방법 2가지
1. .btn-top에 부모요소와 조부모요소(?)를 감싸서 조부모 요소에는 position:absolute; 부모요소에 position:fixed;를 주고 .btn-top에는 버튼 스타일을 지정해준다.
.fixed-area{
position: absolute;
bottom: 0;
right: 90px;
}
.fixed-box{
position: fixed;
bottom: 54px;
z-index: 100;
}
.btn-top{
display: flex;
justify-content: center;
align-items: center;
width: 48px;
height: 48px;
margin: 20px 21px;
opacity: 0.9;
border-radius: 50%;
background-color: rgba(255, 255, 255, 0.9);
color: $colors-gray9;
box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.1);
}
.btn-top{
position: fixed;
bottom: 54px;
left: 50%;
transform:translateX(200px);
display: flex;
justify-content: center;
align-items: center;
width: 48px;
height: 48px;
margin: 20px 21px;
opacity: 0.9;
border-radius: 50%;
background-color: rgba(255, 255, 255, 0.9);
color: $colors-gray9;
box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.1);
} 입력하세요
https://developer.mozilla.org/ko/docs/Web/CSS/CSS_Images/Using_CSS_gradients
css 그라디언트 속성 정의
https://cssgradient.io/
css 그라디언트 제작 사이트
쇼핑몰 리스트 레이아웃을 효율적으로 디자인하기 위해 리스트 공통 디자인 요소를 scss를 활용하여 정리했다.
폰트컬러 변수 할당
$font-kr1:'Noto Sans KR', sans-serif;
$colors-coral10: #FFF5F0;
$colors-coral20: #F9CEC2;
$colors-coral40: #FEB49B;
$colors-coral60: #FE8F71;
$colors-coral80: #FE7B66;
$colors-coral100: #FF6F61;
$colors-coral100_disabled: #FFB7B0;
$colors-coral150: #FF473D;
$colors-green80: #008282;
$colors-green100: #0B666A;
$colors-dark1: #000000;
$colors-gray9: #222222;
$colors-gray8: #3B3B3B;
$colors-gray7: #696969;
$colors-gray6: #A1A1A1;
$colors-gray5: #C4C4C4;
$colors-gray4: #DADADA;
$colors-gray3: #ECECEC;
$colors-gray2: #F3F3F3;
$colors-gray1: #F8F8F8;
$colors-white: #FFFFFF;
_title.scss 리스트 레이아웃의 제목 섹션 공통 디자인
.title-box{
position: relative;
padding: 16px 20px;
.title{
display: flex;
align-items: center;
font-size: 22px;
line-height: 150%;
font-weight: 700;
color: $colors-gray9;
word-break: keep-all;
@include ellip(150%, 2);
margin-bottom: 4px;
img{
display: inline-block;
width: 24px;
height: 24px;
margin-left: 1px;
vertical-align: -4px;
object-fit: contain;
}
}
.desc{
display: flex;
align-items: center;
font-size: 16px;
line-height: 150%;
font-weight: 500;
color: $colors-gray6;
img{
display: inline-block;
width: 16px;
height: 16px;
vertical-align: -4px;
}
}
.link-more{
position: absolute;
right: 16px;
top: 20px;
}
}
_product.scss 쇼핑몰 리스트 레이아웃 공통 디자인 영역
.product-main,
.product-item{
.thumb-box{
position: relative;
img{
border-radius: 12px;
}
}
.badge-box{
position: absolute;
top: 10px;
left: 10px;
}
.sale{
display: inline-flex;
align-items: center;
justify-content: center;
height: 18px;
padding: 4px;
margin-right: 4px;
line-height: 11px;
font-size: 11px;
font-weight: 700;
border-radius: 4px;
text-transform: uppercase;
color: $colors-white;
background-color: $colors-coral150;
}
.new{
display: inline-flex;
align-items: center;
justify-content: center;
height: 18px;
padding: 4px;
line-height: 11px;
font-size: 11px;
font-weight: 700;
border-radius: 4px;
text-transform: uppercase;
color: $colors-coral100;
background-color: $colors-coral10;
}
.cart{
position: absolute;
bottom: 10px;
right: 10px;
width: 40px;
height: 40px;
padding: 8px;
border-radius: 50%;
color: $colors-white;
box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.1);
background-color: rgba($color: #000000, $alpha: 0.6);
}
.info-box{
padding: 10px 0;
display: flex;
flex-direction: column;
}
.free-delivery{
display: flex;
font-size: 13px;
line-height: 160%;
color: $colors-gray6;
}
.current-sale{
color: $colors-coral100;
font-weight: 700;
del{
color: $colors-gray6;
font-weight: 400;
}
}
.product-name{
color: $colors-gray8;
font-weight: 500;
}
.price{
em{
font-weight: 700;
margin-right: 2px;
color: $colors-gray8;
.sc-type4 &{
color: $colors-coral100;
}
}
}
}