TIL | 09/20/2022

블로그 이사 완료·2022년 9월 20일
0
post-thumbnail

# CSS position ( relative / absolute )

학원 강의로 CJ ONE 메인 페이지 클론코딩 중이다.

아직 CSS를 작성 할 때 position의 relativeabsolute의 적절한 사용법에 익숙치 않다.

확실하게 알고 있는 것은 부모에 position:relative; 로 기준을 잡으면 자식 요소에 position:absolute; 를 선언 시 부모 기준으로 위치 지정이 가능하다는 것이다.

CJ ONE 페이지 제작이 끝나면 내가 혼자서 하나의 페이지를 클론 코딩해야한다. 이번 예제 전에 확실하게 공부 해야겠다.


# 클래스 [ .on] 으로 스타일 작성 구분

HTML과 CSS만으로는 웹 표현에 한계가 있다. 사용자와 상호작용에 한계가 있기 때문이다. (hover 등)

이 때문에 상호작용에 사용하는 Javascript를 사용하는데 주로 문서객체조작(DOM)으로 HTML마크업에 클래스 on 을 추가/삭제 하는 방법을 사용한다.

그래서 CSS는 기본 구조에 대한 코드를 작성 해놓고, 클래스에 on 이 추가 되었을 때 표현되는 코드를 따로 작성해놓아야 한다.

//주메뉴
const headerWrap = document.querySelector('.header_wrap');
const gnbMenu = document.querySelectorAll('.gnb>ul>li');
const subMenu = document.querySelectorAll('.gnb>ul>li>ul');

for (let i = 0; i < gnbMenu.length; i++) {
  gnbMenu[i].addEventListener('mouseover', () => {
    headerWrap.classList.add('on');
    subMenu.forEach((item) => {
      item.classList.add('on');
    });
  }); //mouseover

  gnbMenu[i].addEventListener('mouseout', () => {
    headerWrap.classList.remove('on');
    subMenu.forEach((item) => {
      item.classList.remove('on');
    });
  }); //mouseout

  gnbMenu[i].children[0].addEventListener('focus', () => {
    headerWrap.classList.add('on');
    subMenu.forEach((item) => {
      item.classList.add('on');
    });
  }); //focus

  gnbMenu[i].children[0].addEventListener('blur', () => {
    headerWrap.classList.remove('on');
    subMenu.forEach((item) => {
      item.classList.remove('on');
    });
  }); //blur
}

위와 같은 풀다운 메뉴는 여러개의 li태그를 for문으로 li태그의 배열을 반복하면서 해당 요소에 이벤트 발생 시 클래스에 on을 추가/삭제 하는 구조다.(웹 표준성에 따라 focus/blur도 지정해줘야한다.)

// 검색열기닫기
const srchBox = document.querySelector('form.srch');
const srchOpen = document.querySelector('.srch_open');

srchOpen.addEventListener('click', (e) => {
  e.preventDefault();
  e.currentTarget.classList.toggle('on');
  srchBox.classList.toggle('on');

  if (e.currentTarget.classList.contains('on')) {
    e.currentTarget.children[0].setAttribute('title', '검색입력서식 닫기');
  } else {
    e.currentTarget.children[0].setAttribute('title', '검색입력서식 열기');
  }
});

위와 같은 간단한 드롭다운 메뉴는 toggle() 을 사용해서 클릭 할때마다 .on 이 추가/삭제 되도록 할 수 있다.
툴팁이 있을 땐 툴팁 내용도 변경 해주는 것이 옳다. 클래스에 .on이 추가 되었는지 확인하는 방법은 .contains('on')을 사용하면 된다.
on이라는 클래스의 유무에 따라 불리언 값을 반환해준다.

// 로그인 이미지
const loginAppear = document.querySelector('.info>.login>.appear');

let appear = '';
for (let i = 0; i < 57; i++) {
  if (i < 10) {
    appear += `<img src="images/appear/appear_0000${i}.png" />`;
  } else {
    appear += `<img src="images/appear/appear_000${i}.png" />`;
  }
  loginAppear.innerHTML = appear;
}

// 로그인 애니메이션
// appear 57개 이미지, 딜레이 0.05s 씩 증가
// animation: ani 2.85s linear 0s 1;
const appearAni = loginAppear.querySelectorAll('img');
for (let i = 0; i < appearAni.length; i++) {
  appearAni[i].style.animation = `ani 2.85s linear ${i * 0.05}s 1`;
}

위와 같이 여러가지 이미지를 영상처럼 표현하는 법은 다음과 같다
1) 이미지 개수만큼 변수 생성하고 innerHTML로 이미지 태그의 값을 할당한다.
2) 생성된 이미지에 CSS animation을 for문으로 딜레이 값을 계속 증가시킨다.


# 스프라이트 기법

기업에서는 주로 한개의 이미지 안에 여러 이미지를 넣어놓고 position을 조정해서 원하는 이미지만 사용하는 스프라이트 기법을 사용한다.
아래 코드의 background 이미지는 모두 하나의 파일을 링크로 가져온다. 하지만 사이트에 나타나는 이미지는 다르다.

section > .banner_arrow > a.btn_prev {
    background: url(../images/btn_banner.png) no-repeat 0 0;
}
section > .banner_arrow > a.btn_next {
    background: url(../images/btn_banner.png) no-repeat -50px 0;
}
section > .banner_rolling > p {
    background: url(../images/btn_banner.png) no-repeat -100px -30px;
}
section > .banner_rolling > ul > li {
    background: url(../images/btn_banner.png) no-repeat -130px 0px;
}


이처럼 하나의 파일에 여러가지 이미지가 들어 있고 CSS로 background-position 값을 변경해서 원하는 이미지를 사용한다.

아래는 네이버에서 사용하는 스프라이트 이미지다.

왜 쓰는걸까?
이미지가 사용될 때마다 웹 브라우저는 서버에게 이미지를 요청해야 한다. 요청하고 처리되는 과정이 일괄적으로 이루어지지 않기 때문이다.
따라서 필요한 이미지의 개수는 서버에 보내는 요청의 수와 비례하며 이는 페이지의 로딩 시간과 직결된다.

정리를 해보면,

  • 서버로의 요청 횟수를 줄여 사이트 로딩 속도를 줄여준다.
  • 많은 이미지 파일을 관리하는 대신 하나의 스프라이트 이미지 파일만 관리하면 된다.

단점도 있다.

  • 당연한 얘기지만 이미지 개수가 늘어남에 따라 스프라이트 자체의 용량이 커질 수 있다.
  • 일부 이미지, 로고의 수정이 필요한 경우 유지 보수가 까다롭다. 그렇기 때문에 웬만하면 수정이 안될 것 같은 단순한 이모티콘이나 로고의 경우에 자주 쓰인다.

# 클린코드를 작성하자

오늘만 해도 자바스크립트로 코드 작성 할때 간단한 비교연산자 사용만으로 코드가 더 간결해지고 이해하기 쉬웠던 적이 있었다.

// 고객센터에 .on 붙어있으면 .on삭제
// 검색박스에 .on 붙어있으면 .on삭제
if (csBtn[4].classList.contains('on') || srchOpen.classList.contains('on')) {
  csBtn[4].classList.remove('on');
  srchOpen.classList.remove('on');
  srchBox.classList.remove('on');
}

if문의 조건 안에는 불리언 값이 와야하는 것과 classList.contains() 의 반환 값이 불리언 값인 것을 활용해서 작성한 코드다.

알고리즘 문제를 조금씩 풀어보니 이렇게 도움이 되는 것을 느꼈다.


오늘 끝, 내일 안녕

profile
https://kyledev.tistory.com/

0개의 댓글