반응형 디자인을 더욱 쉽게 구현하기 위해 기존 CSS에서 SCSS로 전환을 결정하였다. SCSS 도입으로 코드의 효율성과 재사용성을 높이고, 보다 쉽게 다양한 화면 크기에 유연하게 대응하는 반응형 웹페이지를 제작할 수 있었다.
먼저, 미디어 쿼리 및 자주 사용되는 디자인 패턴을 믹스인으로 정의하여 프로젝트 전체에서 재사용할 수 있도록 하였다.
/* 텍스트 오버플로우 스타일 정의 */
@mixin ellipse($line:1) {
overflow: hidden;
text-overflow: ellipsis;
word-break: keep-all;
word-wrap: break-word;
@if($line > 1) {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: $line;
} @else {
white-space: nowrap;
}
}
/* 미디어 쿼리 믹스인을 사용하여 반응형 디자인 구현을 단순화 */
@mixin desktop() {
@media (max-width: 1539px) {
@content;
}
}
@mixin desktop-small() {
@media (max-width: 1399px) {
@content;
}
}
@mixin laptop() {
@media (max-width: 1199px) {
@content;
}
}
@mixin tablet() {
@media (max-width: 1023px) {
@content;
}
}
@mixin mobile() {
@media (max-width:767px) {
@content;
}
}
또한, HTML 구조 변경 없이 display: flex
와 display: grid
를 활용하여 SCSS 코드만으로 레이아웃을 조정하여 반응형 디자인을 구현해냈다.
.sc-solution .solution-list {
display: flex; /* 기본으로 flex 디스플레이 사용 */
width: 100%;
@include tablet() {
display: grid; /* 태블릿 사이즈에서 grid로 변경하여 레이아웃 조정 */
grid-template-columns: repeat(2, 1fr);
grid-row-gap: 64px;
}
@include mobile() {
display: flex; /* 모바일 사이즈에서 다시 flex 사용하되, 방향 변경 */
flex-direction: column;
}
}
SCSS 도입 후, 반응형 디자인 구현 시간을 줄일 수 있었으며, 스타일 시트 유지 관리도 좀 더 간편해졌다. 이러한 과정에서 코드의 모듈화와 재사용성의 중요성을 깊히 이해하게 되었고, 더욱 체계적이고 효율적인 방법으로 스타일을 관리하는 방법을 배울 수 있었다.
비디오 진행률에 따른 프로그레스바 구현 중 몇가지 문제에 직면했다. 아래에 그 해결 과정을 기록해보고자 한다.
.sc-intro .control-area .progress-area #progress-bar {
display: block;
width: 0;
height: 100%;
background-color: #fff;
transition: width 0.3s linear;
}
프로그레스 바 진행 시 부드러운 움직임을 위해 transition을 사용했는데, 이는 비디오 재생 시에는 원활하게 동작했으나, 비디오가 끝나고 처음으로 돌아갈 때 즉, 너비가 100%에서 0%로 돌아가는 과정에서도 transition이 적용되어 부자연스러운 동작을 유발했다.
var introVideo = document.getElementById("intro-video");
var videoBtn = document.getElementById("video-btn");
var progressBar = document.getElementById("progress-bar");
videoBtn.addEventListener("click", function () {
if (introVideo.paused) {
introVideo.play();
videoBtn.classList.remove("play");
} else {
introVideo.pause();
videoBtn.classList.add("play");
}
});
introVideo.addEventListener("timeupdate", function () {
var progress = (introVideo.currentTime / introVideo.duration) * 100;
progressBar.style.width = progress + "%";
프로그레스바의 진행도와 비디오의 실제 진행시간이 정확히 일치하지 않는 문제가 발생했다. timeupdate
가 비디오 재생 중 일정한 간격으로 발생하기 때문에, 프로그레스바의 업데이트 주기와 비디오의 실제 재생 시간이 완벽히 동기화되지 않아서 발생한 문제였다.
introVideo.addEventListener("loadedmetadata", function () {
const barMotion = gsap.to("#progress-bar", introVideo.duration, {
repeat: -1, // 무한 반복
width: "100%",
paused: true,
ease: "none",
});
introVideo.play();
barMotion.play();
videoBtn.addEventListener("click", function () {
if (introVideo.paused) {
introVideo.play();
barMotion.play();
videoBtn.classList.remove("play");
} else {
introVideo.pause();
barMotion.pause();
videoBtn.classList.add("play");
}
});
});
이러한 문제를 해결하기 위해 GSAP의 타임라인 기능을 활용했다. loadedmetadata
이벤트 리스너 내부에서 gsap.to
를 사용하여 프로그레스바의 너비를 0%에서 100%까지 변화시키는 애니메이션을 정의하고, 이를 비디오의 duration
과 동기화하여 비디오 재생과 일치하게 만들었다.
위와 같이 수정함으로써 비디오 재생이 끝나고 처음으로 돌아갈 때의 transition 문제도 해결할 수 있었다.
💡loadedmetadata란?
loadedmetadata
이벤트는<audio>
나<video>
요소가 메타데이터(예: 지속 시간, 차원, 텍스트 트랙 등)를 완전히 로드하고 사용할 준비가 되었을 때 발생한다.
예를 들어, 비디오 플레이어를 구현할 때,loadedmetadata
를 활용하면 미디어의 총 재생 시간을 알아내거나, 미디어의 원본 크기 같은 정보를 기반으로 UI를 조정할 수 있다. 또한, 이 이벤트를 사용하여 미디어가 재생될 준비가 되었는지 확인한 후에 사용자에게 재생 컨트롤을 제공할 수도 있다.
웹사이트의 전체적인 디자인과의 조화를 위해 사용자가 많이 접하는 부분 중 하나인 헤더의 드롭다운 메뉴에 커스텀 스크롤바를 적용했다.
.sub-nav::-webkit-scrollbar {
width: 4px; /* 스크롤바 너비 설정 */
}
.sub-nav::-webkit-scrollbar-track {
background: #fff; /* 스크롤바 배경색 설정 */
}
.sub-nav::-webkit-scrollbar-thumb {
background: #bfc6d2; /* 스크롤바의 움직이는 부분 색상 설정 */
border-radius: 4px;
}
위와 같이 커스텀함으로써, 디자인의 일관성을 유지하고 기본 스크롤바와 차별화된 디자인으로 사용자에게 더 나은 경험을 제공할 수 있게 되었다.
웹사이트의 사용자 경험을 향상시키는 중요한 요소 중 하나는 스크롤 동작이 얼마나 부드러운지이다. 이번 프로젝트에서는 Lenis 라이브러리를 도입하여 'Top 버튼' 클릭 시, 최상단으로 부드럽게 이동하는 기능을 구현했다.
💡Lenis 소개
Lenis는 스크롤 퍼포먼스를 개선하고 사용자에게 부드러운 스크롤 경험을 제공하기 위해 설계된 자바스크립트 라이브러리이다. 이 라이브러리는 스크롤 이벤트를 최적화하고, 다양한 애니메이션과의 통합을 용이하게 한다.
const lenis = new Lenis(); // lenis 객체 생성
lenis.on("scroll", (e) => { // 스크롤 이벤트 리스너 등록
});
lenis.on("scroll", ScrollTrigger.update);
gsap.ticker.add((time) => { // gsap의 ScrollTrigger와 lenis 스크롤 이벤트 동기화
lenis.raf(time * 1000); // lenis 애니메이션 프레임 업데이트
});
gsap.ticker.lagSmoothing(0); // 애니메이션 지연 최소화
.
.
.
document.querySelector(".top-btn").addEventListener("click", function () {
lenis.scrollTo(0); // top-btn 클릭 시, 최상단으로 부드럽게 이동
});
Lenis를 활용한 'Top 버튼'을 구현함으로써, 사용자가 보다 쉽게 페이지의 최상단으로 돌아갈 수 있도록 하였다. 사용자에게 부드러운 스크롤 애니메이션을 제공하여 만족도를 높이고 웹사이트의 전반적인 사용자 경험을 개선하였다.