mypage 만들기

seul_velog·2022년 1월 19일
0
post-thumbnail

✍️ 자기소개 페이지를 만들어보면서 메모한 내용들 + 문제해결 과정

1. CSS 선택자

  • 선택자 띄어쓰기
    .box .box1
    : box 컨테이너안에 들어있는 자식 요소중에 box1을 꾸며줄 때

  • .box.box1
    : box이면서 box1인 요소를 꾸며줄때 (즉 두개의 클래스를 다 가지고 있는 교집합)



2. position

포지션 적용이 안되는 이유 / sticky & fixed

  • ❗️주의할 점
    - width와 height 값을 주어도 변동이 안되는 것은 기본 static 속성 때문이다.
    - sticky 속성은 포지션(top, left) 지정을 해주지 않으면 반영되지 않는다.
    - sticky는 그자리에서 고정, fixed는 기존 위치에서 나와서 뷰포트 기준이다.

  • sticky와 fixed의 차이
    - sticky : sticky를 선언한 영역의 부모 요소 안에서만 고정되어 스크롤에 따라 움직이게 된다. (부모요소 기준)
    - fixed : 페이지 전체 영역을 기준으로 고정된다.



3. blockElement 수평정렬

  • 블럭요소는 브라우저에서 자동으로 마진을 꽉채워준다. (보통 오른쪽)
    - 그래서 margin: auto 시 가운데로 정렬되는 것이다. (이때의 margin은 수평만 따지므로 수평정렬이다.)
  • 블록요소 안의 컨텐츠들은 text-align:center
    - text-align은 텍스트가 아닌 인라인요소(버튼 등)도 정렬가능하다.
    - div의 경우 이미 마진이 포함되어있는 블록 요소이므로 작동하지 않는다.



4. 수직정렬

  • transform: translate(50%, 50%);
  left: 50%;
  transform: translateX(-50%);
  • 다른 방법도 있겠지만 플렉스박스에 포함되지 않는 간단한 요소에는 이 방법을 썼다. translate는 자기 자신의 퍼센트를 계산하므로 부모의 50%로 이동시켜줘야 한다.

  • 예제 코드 ▼

.item {
 top: 50%;
 left: 50%;
 transform: translate(-50%, -50%);
}
  • ❓다시 translate를 사용해서 -50%씩 이동시켜 줘야하는 이유.
    : top: 50% , left: 50% 로 요소를 이동시키면, 좌측상단 모서리가 부모 요소의 중앙으로 이동한다. 그래서 요소의 중심은 부모의 중심과 일치하지 않게되기 때문이다. [참고한 글]



5. line-height 속성으로 정렬

  • display 속성이 block, inline-block 으로 지정된 박스 블록 요소에는 line-height 속성을 적용해 박스 안에 있는 인라인 요소, 또는 인라인 태그에 행 높이를 적용할 수 있다.
    - 요소를 배치할 때 부모 요소의 높이만큼 행 높이를 line-height 값으로 지정하면 인라인 속성인 요소가 수직으로 가운데 정렬이 된다.

  • ❗️한줄 텍스트에만 유효하다. 이 뜻은, 인라인 요소가 2줄 이상으로 표시되는 경우, 2번째 줄 이후의 내용이 부모 요소의 바깥에 표시되는 문제생긴다. 그러므로 짧은 인라인 요소를 수직 중앙정렬할 때 유의해서 사용하자.

#navbar ul li {
  padding: 20px;
  border: 1px solid var(--color_white);
  border-radius: 50%;
  width: 16px;
  height: 16px;
  margin-top: 20px;
  text-align: center;
  line-height: 16px;
  color: var(--color_white);
  transition: all 300ms ease-in-out;
  font-weight: bold;
}

6. li 태그 세로로 나열하기 (오류해결)

#promise .profile_text {
  display: flex;
  flex-direction: column;
}
  • 🤔 이렇게 주어도 column이 적용되지 않았다. 즉 세로로 정렬되지 않았다. 부모에게 준 속성을 뜯어보고 정확히 원하는 요소에 속성을 맞게 주었는지 확인해 보았지만 원하는 모양이 나오지 않았다.

  • css 파일을 만들고 초반에 정의해 둔 all:unset 을 지웠다.
    → 해결 ! 세로로 정렬되었다.

  • ❗️all: unset 유의할 점
    - 리스트의 중점 · 은 사라지지만 리스트 목록들을 세로로 정렬하는 순수 리스트의 기능 마저 사라진다. 때문에 가로로 나열되어 원하지 않는 결과를 볼 수 있으니 조심하자.
    → 이럴 땐 ul {list-style: none;} 으로 하기

  • 혹은 all:unset 을 그대로 주면서 원하는 배치를 할 수 있을지 시도해 보았다.

#promise ul {
  display: flex;
  flex-direction: column;
}

이렇게 선택자명을 ul로 두었더니 지우지 않고도 원하던 대로 수직정렬 되었다. 😀



7. 가상 요소 선택자(Pseudo-Element Selector)

  • 가상 요소는 요소의 특정 부분에 스타일을 적용하기 위하여 사용된다.
    ::before 콘텐츠의 뒤에 위치하는 공간을 선택한다. (지정한 요소 뒤에 가상 콘텐츠를 삽입한다.)
    ::after 콘텐츠의 앞에 위치하는 공간을 선택한다. (지정한 요소 앞에 가상 콘텐츠를 삽입한다.)
    ::first-letter 콘텐츠의 첫 글자를 선택한다.
    ::first-line 콘텐츠의 첫 줄을 선택한다.
    ::selection 드래그한 콘텐츠를 선택한다.
.home_section::before {
  display: block;
  position: relative;
  content: "";
  width: 150px;
  height: 2px;
  top: 142px;
  left: 70px;
  transform: translateX(-50%);
  margin-top: 8px;
  background-color: var(--color_lightGray);
}
  • ::before와 ::after를 쓸 때는 content가 꼭 필요하다.
    - 같이 쓰이는 content=""; 은 가짜 속성이다. html 문서에 정보로 포함되지 않은 요소를 CSS에서 새롭게 생성시켜 준다.

✍️ 디자인을 제어할 때 효율적으로 스타일을 주기에 좋은 방법이지만, 접근성 이슈들 또한 고려해야할 것 같다. (특정 스크린리더나 브라우저(IE)에서는 읽히지 않는 등) [참고한 글]



8. 마우스 호버시 글자가 보이지 않도록 설정하기

.like_this_texts {
  position: absolute;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  left: 50%;
  transform: translateX(-50%);
  color: var(--color_white1);
  background-color: rgb(172, 139, 139);
  width: 100%;
  height: 100%;
  transition: all 300ms ease-in-out;
}

.like_this_texts:hover {
  background-color: rgba(0, 0, 0, 0.1);
  opacity: 0;
}
  • 처음엔 .like_this_texts:hover 에서 display:none 으로 설정 했는데 글자가 끊기듯이 사라졌다.

  • ✍️ 애니메이션 효과까지 적용하기를 원한다면 display:none 처럼 보이지 않도록 하는 속성대신, 투명도 속성 opacity 로 설정하자. 이렇게 수정해서 원하는 애니메이션 효과를 얻을 수 있었다.



9. 이미지 비율 조정 및 설정하기

  • 처음에 이미지의 사이즈 설정을 background-size: cover 로 했더니 이미지 내부의 가로세로 비율이 맞지 않았다.

  • 구글링을 통해서 object-fit: cover 이라는 속성을 알게 되었고, 적용 후 비율이 깨지지 않게 되었다.

  • object-fit
    [MDN_object-fit]
    <img><video> 같은 오브젝트의 사이즈를 컨테이너의 크기에 맞춰 조절할 수 있다.
    ❗️ IE에서는 지원되지 않는다.

  • object-fit:cover 를 쓰면 가로세로 비율은 유지하면서 컨테이너에 꽉 차도록 설정된다. 너비와 높이값을 입력하고, object-fit 속성을 지정한다.

  • object-fit의 속성

    object-fit: fill - 이미지가 강제로 늘어나거나 줄어들면서 지정한 넓이, 높이에 꽉 찬다. 원본 이미지의 비율을 유지하지 않는다.
    object-fit: contain - 원본 이미지의 비율을 유지하면서 지정한 넓이, 높이안에서 최대한 확대시킨다. 잘리는 부분이 발생하지 않는다.
    object-fit: cover - 원본 이미지의 비율을 유지하면서 지정한 넓이, 높이에 꽉 찬다. 잘리는 부분이 발생한다.
    object-fit: none - 지정한 넓이, 높이에 상관없이 원본 이미지의 크기를 유지한다. 원본 이미지 가운데 부분이 보여지게 된다.
    object-fit: scale-down - 지정한 넓이, 높이값보다 원본 이미지가 작으면 그대로 두고, 크면 원본이미지 사이즈를 줄여서 보여준다.



추가)

10. Typing Effect

const titleText = document.querySelector("h1.title");
let i = 0;
let txt = "Hello, I'm seulbi !";
let speed = 90;

function typeWriter() {
  if (i < txt.length) {
    titleText.innerHTML += txt.charAt(i);
    i++;
    setTimeout(typeWriter, speed);
  }
}
typeWriter();
  • 변수 itxt 를 선언하고, if문 안에서 글자를 만들어 낸다음 setTimeout 을 통해서 동작 효과를 구현한다.

  • String.prototype.charAt()
    : charAt() 함수는 문자열에서 특정 인덱스에 위치하는 유니코드 단일문자를 반환한다.
    ex.)

const anyString = 'Brave new world';

console.log(`The character at index 1 is '${anyString.charAt(1)}'`);
// "The character at index 1 is 'r'"



11. @keyframes

  • 처음으로 키프레임 애니메이션을 사용해 보았다. 키프레임 변수(appear, disappear)를 만들고 해당 요소에 javascript를 통해서 동적으로 animation 프로퍼티와 값을 추가한다.
// css(scss)
@keyframes appear {
  from {
    top: 50px;
    opacity: 0;
  }
  to {
    top: 105px;
    opacity: 1;
  }
}

@keyframes disappear {
  from {
    top: 105px;
    opacity: 1;
  }
  to {
    top: 50px;
    opacity: 0;
  }
}
// js
const promiseContainer = document.querySelector(".promise_container");
window.addEventListener("scroll", () => {
  let value = window.scrollY;
  if (value > 1700) {
    promiseContainer.style.animation = "appear 1s ease-out forwards";
  } else {
    promiseContainer.style.animation = "disappear 1s ease-out";
  }
});
  • 이벤트리스너를 등록, 'scroll' 이벤트를 통해서 조건에 따라 애니메이션 속성을 넣어준다.



12. nav scroll 핸들러 동작과 JS리팩토링(1)

  • nav ul컨테이너의 li 버튼들을 누르면 해당 section으로 scroll되도록 javascript로 구현하였다.
const nav = document.querySelector(".navbar_container");
const liH = document.querySelector(".navMenu:nth-child(1)");
const li1 = document.querySelector(".navMenu:nth-child(2)");
const li2 = document.querySelector(".navMenu:nth-child(3)");
const li3 = document.querySelector(".navMenu:nth-child(4)");
const home = document.querySelector("#home");
const profile = document.querySelector("#profile");
const likes = document.querySelector("#likes");
const promise = document.querySelector("#promise");

liH.addEventListener("click", () => {
  home.scrollIntoView({ behavior: "smooth", block: "start" });
});

li1.addEventListener("click", () => {
  profile.scrollIntoView({ behavior: "smooth", block: "start" });
});

li2.addEventListener("click", () => {
  likes.scrollIntoView({ behavior: "smooth", block: "start" });
});

li3.addEventListener("click", () => {
  promise.scrollIntoView({ behavior: "smooth", block: "start" });
});
  • 처음에는 각각의 태그마다 이벤트를 동작시켰는데, 전체 js코드가 길지 않아서 어떤 코드인지 한번에 알 수 있었지만, 중복되는 코드가 많고 내용에 비해 전역변수가 많이 생성된 구조라고 생각되어서 리팩토링을 하기로 했다.⚡️

✍️

  • <li> 태그를 다 가져와서 하나씩 이벤트리스너를 다 등록하는 것은 좋지 않다.
  • <ul> 태그를 한번만 가져와서 리스너를 등록하는게 좋음!

  • ❗️ 만약 ul 을가져올 때 querySelectorAll 로 가져오면 배열을 리턴하기 때문에 배열에다가는 addEventListener()를 추가 할 수 없으니 에러가 난다. 유의!
  • 이벤트 버블링 : 부모 컨테이너는 어떤 자식 요소에서 이벤트가 발생하는 모든 이벤트를 다 들을 수 있다.
const nav = document.querySelector(".navbar_container");

nav.addEventListener("click", (e) => {
  const target = e.target;
  const li = target.dataset.li;
  scrollF(li);
});

function scrollF(selector) {
  const scrollSec = document.querySelector(selector);
  const scrollY = scrollSec.offsetTop;
  window.scrollTo({ top: scrollY, behavior: "smooth" });
}
  • ul 컨테이너를 querySelectorAll 이 아닌, querySelector 로 가져온다.
  • html 속성으로 dataset 을 사용, js 에서 해당 data를 가져와서 활용한다.
  • scrollSec 변수에 각각의 section 을 담는다.
  • scrollY 변수에 HTMLElement.offsetTop 속성으로 각각의 section 위치를 담는다.
  • window.scrollTo 로 동작시키자.

📌 추가적으로 nav 컨테이너 안에서 li 가 아닌 여백을 클릭해도 이벤트 콜백함수가 계속 실행된다.

버튼이 클릭 되었을 때만 이벤트 처리를 하도록 코드를 추가하자.▼

 if (target.tagName !== "LI") return;

이제 버튼을 클릭할 때만 동작된다! 😀



13. map()을 이용한 JS리팩토링(2)

13-1. 키프레임을 활용한 텍스트 애니메이션

  • @keyframes 애니메이션을 개별 텍스트에 적용했다.
  • 위에서는 position:absolute 과 위치속성을 이용했지만, 이번에는 transform: translateY 속성으로 이동시켰다.
  @keyframes up {
    from {
      transform: translateY(55px);
      opacity: 0;
    }
    to {
      transform: translateY(0);
      opacity: 1;
    }
  }
  @keyframes down {
    from {
      transform: translateY(0);
      opacity: 1;
    }
    to {
      transform: translateY(55px);
      opacity: 0;
    }
  }

13-2. javascript scroll이벤트와 리팩토링

  • 그런데 javascript에서 html 요소를 어떻게 가져올지 고민이 되었다.🤔 우선 nav scroll을 구현 했을 때처럼 코드를 작성했다.

❗️ 문제점)

  • nav scroll에서의 리팩토링 하기 전 코드와 마찬가지로 전역 변수가 많아지고, 하나하나 개별적으로 속성을 적용하면 코드가 계속 중복된다.
  • nav 처럼 ul 컨테이너를 가져오듯 querySelector 로 가져올 수 없는 상황이다. 따라서 querySelectorAll 로 해당 div 태그를 전부 한번에 가져오면, 유사배열객체 NodeList 를 반환한다.

✍️ 해결과정)

  • 반환된 NodeList에서 각각의 요소를 편리하게 사용하기 위해 배열로 만들어 주면 어떨까?
  • Array.from을 활용한다. 콘솔로 출력해보니 원했던 html요소가 잘 반환 되었다. 이걸 어떻게 활용할까?
  • Array.from을 이용해서 배열로 만든 것을 변수에 할당하고 기존에 작성해 둔 코드 내부에서 map()을 이용한다. → 작동된다! 😊

❓ 작성한 코드를 보다보니 scroll이 될 때마다 window.scrollY를 호출해서 그 값을 value 변수에 담아 함수 내부에서 사용되고 있는데 이 코드를 전역 변수로 선언하면 scroll 이벤트 발생시마다 위치값을 알 수가 없을테고, 어떻게 리팩토링하면 좋을까? 🤔

const likesTitleContainer = document.querySelectorAll(".like_title div");
const likesTitleArray = Array.from(likesTitleContainer);

window.addEventListener("scroll", () => {
  let value = window.scrollY;
  likesTitleArray.map((i) => {
    if (value > 1100) {
      i.style.animation = "up .6s ease-out forwards";
    } else {
      i.style.animation = "down 1s ease-out ";
    }
  });
});

13-3. scroll 이벤트로 nav 색상 변경하기

const navLis = document.querySelectorAll(".navbar_container .navMenu");
const navLisArray = Array.from(navLis);
window.addEventListener("scroll", () => {
  let value = window.scrollY;
  navLisArray.map((li) => {
    if (value > 200) {
      li.classList.add("dark");
    } else {
      li.classList.remove("dark");
    }
  });
});
  • 위에서 작성한 코드를 바탕으로, 스크롤이 window 화면에서 일정이상 내려가면 nav의 li들에게 css 속성을 추가하거나 제거하는 방법을 통해서 색상 투명도를 조정해 보았다.
  • 위와 마찬가지로 Array.frommap() 함수를 이용했다. 😀

✍️ 추가로 css를 scss로 리팩토링도 해보았다. :root 대신 $ 변수로 바꾸고 정리해보았는데 전체적으로 잘 작동되었다.

profile
기억보단 기록을 ✨

0개의 댓글