자기소개 웹페이지를 드디어 완성했습니다~!🎉 UI 디자인부터 구현한 자바스크립트 기능, 그리고 페이지를 만들며 느끼고 배운점들에 대해 글로 남겨요.
자바스크립트로 만든 기능은 아래와 같이 총 5가지입니다. 이 기능들을 중점적으로 코드를 하나하나 자세히 보며 설명해보려고 해요💁
- 상단 이동 스크롤 버튼
- 타이핑 효과
- 이미지 슬라이드
- 모달창
- 진행바 (Progress bar)
기능에 대해 말하기에 앞서서! 전 figma로 먼저 디자인을 해본 뒤, 페이지를 만들었어요. 대충이라도 디자인을 구상하고 코드를 짜야 조금이라도 더 빨리 페이지를 만들어낼 수 있더라구요. 코드를 짜며 그때그때 필요한 부분을 보완했기 때문에 보완한 내용을 figma에 아직 100% 반영하진 않았습니다.
가장 신경쓴 것은 "깔끔하고 가독성이 좋은지!"였어요🤔 자기소개 페이지이기도 하고, 나중에 내 포트폴리오 페이지가 될 수도 있기 때문에, 어떤 사람이 봐도 한 눈에 들어왔으면 좋겠다는 마음이 컸어요. 그래서 사용하는 색들도 최대한 덜어냈습니다.
색조합을 위해 저는 pinterest에서 다양한 자료들을 찾아봤어요. 그 중에서 가장 마음에 드는 자료의 색상을 참고해 아래의 색조합을 주축으로 구성했답니다. 오묘한 색이라 끌렸던 컬러! 블루베리 색이라고 해야하나..?🍇 색이 차분하면서도 부분부분 포인트가 돼서 마음에 들더라구요-!
제일 처음 만든 기능은 상단으로 이동하는 스크롤 버튼이에요. 웹페이지의 어느 위치에서 누르든 맨 위으로 이동할 수 있는 버튼이랍니다. CSS background-image
로 버튼에 이미지를 넣어주었어요. 그리고, 마우스 커서를 버튼에 올렸을 때 background-image
를 다른 이미지로 바꿔줘서 마우스가 올려졌다는 것을 직관적으로 알 수 있게 해줬습니다.
<button onclick="moveToTop()" class="btn-moveTop"></button>
let moveToTop = function () {
document.body.scrollIntoView({ behavior: "smooth" });
};
🖐🏻잠깐! 코드 설명
element.scrollIntoView
는 특정 element를 기준으로 스크롤을 이동시키는 메소드입니다.behavior
라는 매개변수를 통해 전환애니매이션을 정의할 수 있는데요. 기본값은auto
이고,smooth
로 지정하면 부드럽게 스크롤되는 효과를 볼 수 있어요.
MDN | element.scrollIntoView
제목에 집중시킬 수 있는 타이핑 효과를 구현했어요. 처음엔 막막하기만 해서 다른 분들은 어떻게 구현했는지 보며 그 원리를 먼저 익혔어요. 그리곤 제가 이해할 수 있는 코드로 짜보았어요. 후위연산이나 삼항연산자로 더 간단하게 짠 코드가 있었지만, 완전히 와닿지는 않아서요😭 빈 태그에 한 글자씩 넣어주는 것이 핵심이었던 타이핑 효과!
<p class="txt-title"></p>
// 변수 선언
const $txt = document.querySelector(".txt-title");
const content = "안녕하세요 :)\n개발꿈나무 주혜린입니다.";
let contentIndex = 0;
🖐🏻잠깐! 코드 설명
$txt
: HTML의 비어있는 p태그를 가져왔어요. 이 안에 글자를 하나씩 넣어줄거랍니다.content
: 타이핑 될 내용을 적어주었어요.contentIndex
:content
의 첫번째 글자부터 사용하기 위에,0
으로 초기화시켜놓았어요.
// typing 함수
let typing = function () {
$txt.innerHTML += content[contentIndex];
contentIndex++;
if (content[contentIndex] === "\n") {
$txt.innerHTML += "<br />";
contentIndex++;
}
if (contentIndex > content.length) {
$txt.textContent = "";
contentIndex = 0;
}
};
// 0.2초간격으로 typing 함수 실행
setInterval(typing, 200);
🖐🏻잠깐! 코드 설명
$txt
에content
의 글자를contentIndex
0번째부터 하나씩 넣어줍니다.
다음 글자로 넘어가기 위해contentIndex
는 하나씩 증가시켜줬어요.- (조건1) 줄바꿈인
\n
를 만나면, 한 줄 띄어주기 위해<br / >
태그를 넣었어요.
이 때도, 줄바꿈 뒤 다음 다음 글자로 넘어가야 하기 때문에contentIndex
는 하나씩 증가시켰습니다.- (조건2) 맨 마지막 글자까지 모두 화면에 그려졌다면, 다시 비어있는 상태로 만들어 주었어요.
setInterval()
함수를 이용해 0.2초마다 typing함수가 반복될 수 있게끔 해줍니다.
한정된 크기 안에서 여러 사진을 보여주기 좋은 이미지 슬라이드! 5개의 이미지를 가로로 붙여주어 부드럽게 양 옆으로 넘어가도록 만들어주었어요.
헷갈렸던 부분은 위치를 조정해주는 부분이었는데요. 이전 이미지가 아닌 다음 이미지로 넘어가는데 왜 이미지의 가로 길이만큼 원래 위치에서 빼주어야 하는건지 이해가 가지 않았었어요. 앞으로 가는거니깐 당연히 더해주는게 맞다고 생각했죠! 아래처럼 이미지 슬라이드의 구조를 이해하고 나서야 납득이 갔습니다.
이미지 슬라이드는 양옆으로 길게 이미지를 붙여놓고 오른쪽이나 왼쪽을 당김으로써 다른 이미지를 차례로 보여줘요.
위 그림처럼 현재 1번째 이미지가 화면에 보여지고 있다고 가정했을 때, 0번째 이미지를 화면에 보여주기 위해서는 위처럼 길게 이어붙여진 이미지를 오른쪽으로 당겨야해요. 그러면 0번째 이미지는 가로축으로 이미지의 크기인 438px만큼 오른쪽으로 위치가 이동하게 되죠. 그래서 가로방향(x축)으로 +438px
만큼 이동했다고 할 수 있어요. 이전 이미지를 보여주는데 위치값이 +
되는 이유가 이러한 것 때문이었어요. 다음 이미지를 보여준다면 왼쪽으로 당길거기 때문에 위치값이 -
될거구요!
// 변수 선언
const $btnPrev = document.querySelector(".btn-prev");
const $btnNext = document.querySelector(".btn-next");
const $slideImgs = document.querySelector(".slide-images");
const IMG_WIDTH = 438;
let imgIndex = 0;
let position = 0;
🖐🏻잠깐! 코드 설명
$btnPrev
,$btnNext
,$slideImgs
: HTML태그 중, 앞으로가기 버튼와 뒤로가기 버튼, 그리고 이미지들을 묶은 태그를 가져옵니다.imgIndex
,position
: 이미지의 순서가 바뀔때마다 이미지의 위치를 변경시킬 때 사용할 변수를 선언하고0
으로 초기해둡니다.
// 뒤로가기 버튼 클릭 시
let prev = function () {
if (imgIndex > 0) {
$btnNext.removeAttribute("disabled");
position += IMG_WIDTH;
$slideImgs.style.transform = `translateX(${position}px)`;
imgIndex = imgIndex - 1;
}
if (imgIndex == 0) {
$btnPrev.setAttribute("disabled", "true");
}
};
🖐🏻잠깐! 코드 설명
setAttribute
와removeAttribute
: 제일 처음 보이는 이미지는 뒤로가기가 막혀있고, 그 이상의 이미지일 때만 뒤로가기 버튼이 활성화되도록 해줍니다.position += IMG_WIDTH
: 뒤로가기 버튼이지만 왜+
를 해주냐! 이미지 슬라이드는 긴 이미지를 앞으로 당겼다가 뒤로 밀었다가 하는 구조인걸 이해하면 쉬워요. 뒤로가는 것은 긴 이미지를 앞으로 잡아당겨 위치를 조정해주는 것과 같기 때문에, 위치를 이미지의 가로길이만큼 증가시켜주어야해요.
// 앞으로가기 버튼 클릭 시
let next = function () {
if (imgIndex < 5) {
$btnPrev.removeAttribute("disabled");
position -= IMG_WIDTH;
$slideImgs.style.transform = `translateX(${position}px)`;
$slideImgs.style.transition = "transform .5s ease-out";
imgIndex = imgIndex + 1;
}
if (imgIndex == 4) {
$btnNext.setAttribute("disabled", "true");
}
};
🖐🏻잠깐! 코드 설명
- 뒤로가기 버튼과 구조가 같아요.
setAttribute
와removeAttribute
: 맨마지막 이미지가 나왔을 때만disabled
속성을 활성화시킴으로써 앞으로가기 버튼을 눌러도 앞으로 넘어가지 않음을 보여줘요.position -= IMG_WIDTH
: 앞으로가기 버튼이지만, 길게 붙여져 있는 이미지를 뒤로 당겨주어야 앞의 이미지가 보이기 때문에 위치를 이미지 가로길이만큼 빼주었어요.transform .5s ease-out
: 끊기지 않고 부드럽게 넘어가는 효과를 주었어요.
let init = function () {
$btnPrev.setAttribute("disabled", "true");
$btnPrev.addEventListener("click", prev);
$btnNext.addEventListener("click", next);
};
init();
🖐🏻잠깐! 코드 설명
init
함수를 실행시킴으로써 첫이미지의 뒤로가기 버튼을 비활성화시켜두고, 버튼들에 클릭이벤트를 적용시켜놓은 상태로 초기화해놓아요.init
함수가 버튼에 이벤트를 적용시켜주고 있기 때문에init
함수를 실행시키지 않으면 아무런 이벤트도 적용되지 않아요.
취미와 성격에 대한 내용을 각각 확인할 수 있는 모달창을 만들었어요. 처음에는 CSS와 JavaScript에서 이 두개의 모달을 따로 처리해주어서 반복되는 코드가 많았어요🤔 코딩에서 코드를 ctrl+c
ctrl+v
해서 붙여넣고 있다면 굉장히 비효율적으로 코드를 짜고있는 것이라는 얘기를 들은적이 있기에.. 다중 모달을 띄우는 방법을 다룬 글을 통해 해결할 수 있었어요! 함수와 반복문을 사용해서 반복해주면 된다는걸 배웠습니다😇
const $modalBg = document.getElementsByClassName("modal-background");
const $btnOpen = document.getElementsByClassName("btn-open");
const $btnClose = document.getElementsByClassName("btn-close");
🖐🏻잠깐! 코드 설명
$modalBg
: 모달의 모든 내용을 포함하고 있는 부분을 가져왔어요.$btnOpen
과$btnClose
: 모달을 여는 버튼과 닫는 버튼에 같은 클래스명을 주었습니다.
function modal(num) {
$btnOpen[num].addEventListener("click", () => {
$modalBg[num].style.display = "flex";
document.body.style.overflow = "hidden";
});
$btnClose[num].addEventListener("click", () => {
$modalBg[num].style.display = "none";
document.body.style.overflow = "unset";
});
}
for (let i = 0; i < $btnOpen.length; i++) {
modal(i);
}
🖐🏻잠깐! 코드 설명
요소.style.display = "flex"
와요소.style.display = "none"
: 모달을 여는 버튼을 누르면 만들어둔 모달창이 보이게, 모달 닫는 버튼을 누르면 모달창이 보이지 않게 CSS를 JavaScript로 조정해주었어요.요소.style.overflow = "hidden"
와요소.style.overflow = "unset"
: 모달창이 나왔을때 페이지가 스크롤 되지 않게 막아주었어요.
오른쪽의 기존 스크롤바를 없애고 header 하단에 가로 진행바를 넣어주었어요. 스크롤이 긴 페이지가 아닐 뿐더러, header에는 각 페이지 링크, 그리고 왼쪽 하단에는 상단 스크롤 이동 버튼을 넣어줬기 때문에 기존 스크롤바를 없애도 괜찮은 페이지라고 생각했어요.
페이지가 어느정도 진행되었는지 알 수 있기 때문에 시각적으로 좋은 기능인 것 같아요😊 인터렉티브웹 초급편을 수강하며 배웠던 내용을 써봤어요!
body::-webkit-scrollbar {
display: none;
}
🖐🏻잠깐! 코드 설명
- CSS로 기존 스크롤바를 없애주었어요.
webkit
이란?
: webKit은 Safari/Chrome용 HTML/CSS 웹 브라우저 렌더링 엔진이라고 해요.
: webKit 브라우저 스크롤바를 CSS로 커스터마이징 할 수 있고, -webkit-scrollbar는 스크롤바 전체를 의미해요.
let scrollTop = 0;
let bar;
window.onload = function () {
bar = document.getElementsByClassName("bar-ing")[0];
};
🖐🏻잠깐! 코드 설명
window.onload
: HTML의 모든 태그를 불러온 후, 코드 내에 onload가 있을 경우 읽어냅니다. HTML태그가 생성되기도 전에 해당 태그를 불러올 때 생기는 문제를 방지하기 위해 사용한다고 해요.document.getElementsByClassName("bar-ing")[0]
:getElementsByClassName()
메소드는 지정된 클래스 이름을 가진 모든 요소를 NodeList 객체로 반환하고, 이 노드는 인덱스 번호로 액세스할 수 있어요. 따라서[0]
로 몇번째 값인지 써주어야해요!
window.addEventListener(
"scroll",
() => {
scrollTop = document.documentElement.scrollTop; // y축 방향으로 얼만큼 스크롤했는지!
let per = Math.ceil(
(scrollTop / (document.body.scrollHeight - window.outerHeight)) * 100
);
bar.style.width = per + "%";
},
false
);
🖐🏻잠깐! 코드 설명
document.documentElement.scrollTop
: y축 방향으로 내가 얼만큼 스크롤했는 지 그 거리를 알 수 있어요.- 내가 스크롤한 높이 / 웹페이지 높이
: 내가 스크롤한 높이를 웹페이지의 전체높이로 나누어 퍼센트를 구해줍니다.
자기소개 웹페이지를 만들며 JavaScript가 왜 필요한지를 새삼 알 수 있었어요😮 정적이기만 했던 웹페이지에 JavaScript로 다양한 기능을 추가하니 페이지가 더 다채롭고 편리해지더라구요! 그리고 대충 안다고 생각하고 넘겼던 개념들도 다시 한 번 찾아보고 고민할 수 있는 시간이었어요. 나중에는 더 역동적인 페이지도 만들어보고 싶단 생각이 들어요. JavaScript로 코드를 작성하는게 HTML/CSS만큼 편해지는 그 날이 얼른 오기를 바랄뿐..💪🏻❤
맥 크롬에서 UI가 조금 깨져보여요 🥲 한 번 확인해보시면 좋을 듯 합니다 🙏
잘 보고 갑니닷 😁 🙏