ETC/Bootcamp

[패스트캠퍼스 X 야놀자] 프론트엔드 부트캠프 Html, CSS 과제

따봉치치 2023. 8. 7. 19:14
728x90

 

패스트캠퍼스 x 야놀자 프론트엔드 부트캠프 3주차 과제 후기 

 

 


 

웹 페이지 클론코딩 하는 과제였는데 이전 1,2 주차에 배웠던 HTML, css를 활용하여 만드는 과제였다!

나는 개발할 때 마다 css 를 다루는게 어려웠어서 최대한 배운 것을 활용해보고자 KREAM 웹사이트를 선택했다🔥

 

💭 사이트 구조

 

크림 웹사이트 대략적인 구조

크림 사이트 구조는 다음과 같다!

 

상위 Header는 고정이 되어있고 스크롤이 되어도 상단에 떠있는 구조였고

아래 main에는 여러 section으로 구분되어 있었다.

 

시맨틱 태그의 종류는 알고 있었지만 써본 적은 없었어서 이번에는 시맨틱 태그를 적극 활용하여 코드를 작성하였다.!

확실히 div 태그들로만 이루어진 코드보다 가독성이 좋았고 구분하기 쉬워서 다음에도 적극적으로 사용해야겠다 🙇🏻‍♀️

 

실제로 구현된 헤더 부분

 

헤더 부분

 


실제로 구현된 메인 부분


 

실제로 구현된 푸터 부분

 

 

🔨 리팩토링 🔨

 

메인 배너 이미지 확대 이슈

 

멘토님께 코드리뷰를 받으면서 지적받았던 부분으로

배너 이미지를 단순히 width를  100%로 맞춰놓다 보니 윈도우 사이즈가 크면 이미지가 늘어지는 이슈가 발생하였다!!😂

 

이전 코드는 다음과 같다

.banner_section_not_move > .banner >img {
    position : relative;
    width : 100%;
    height : 480px;
    padding : 0;
    margin : 0;

}

 

배너 컨테이너와 이미지 태그를 같이 width를 적용하니까 발생한 문제였다!

 

.banner_section_not_move > .banner {
    position : relative;
    width : 100%;
    overflow : hidden;
    height : 480px;
    padding : 0;
    margin : 0;
    display : flex;


}
.banner_section_not_move > .banner >img {
    margin : 0 auto;
    max-height : 480px;
    

}

배너 컨테이너와 img를 분리하여 컨테이너에만 width를 적용해주니 문제는 간단하게 해결이 되었다~!😆

 

 

 

배너 슬라이드 수정
수정 전

수정 전 배너 슬라이드

수정 전 배너는 단순한 CSS로만 작업하다 보니 keyframe animation으로 작성을 하였고

5초마다 배너가 슬라이딩 형태로 이동되게 코드를 작성하였다.

결과적으로 실제 크림 사이트와는 다르게 움직이고 또한,  슬라이드 페이지네이션이 되지 않았다!!

 

- html 코드

<section class="banner_section">
                <input type="radio" name="slide" id="slide01" checked>
                <input type="radio" name="slide" id="slide02">
                <input type="radio" name="slide" id="slide03">
                <input type="radio" name="slide" id="slide04">
                <input type="radio" name="slide" id="slide05">
                <div class="slide_wrap">
                    <ul class="slide_list">
                        <li>
                            <a>
                                <label for="slide03" class="left"></label>
                                <img src="assets/banner_17.webp">
                                <label for="slide02" class="right"></label>
                            </a>
                        </li>
                        <li>
                            <a>
                                <label for="slide01" class="left"></label>
                                <img src="assets/banner_15.webp">
                                <label for="slide03" class="right"></label>
                            </a>
                        </li>
                        <li>
                            <a>
                                <label for="slide02" class="left"></label>
                                <img src="assets/banner_4.webp">
                                <label for="slide04" class="right"></label>
                            </a>
                        </li>
                        
                        ...
                        
                        <li>
                            <a>
                                <label for="slide03" class="left"></label>
                                <img src="assets/banner_20.webp">
                                <label for="slide01" class="right"></label>
                            </a>
                        </li>
                    </ul>
                </div>
            </section>
            <section class="grid_section">

- CSS 코드

.banner_section input[id*="slide"] {
    display : none;
    
}
.banner_section .slide_wrap {
    margin : 0 auto;
    overflow: hidden;
    max-width: 100%;
    max-height: 480px;


}
.banner_section .slide_list {
    white-space : nowrap;
    font-size : 0;
    padding: 0;
    max-height: 480px;
    
}
.banner_section .slide_list > li {
    display : inline-block;
    vertical-align : middle;
    width: 100%;
    transition: all .5s;
    max-height: 480px;
    justify-content: center;
    text-align: center;
    animation: slideAnimation 25s infinite;
    opacity: 0;
    
}

@keyframes slideAnimation {
    0%, 20% { transform: translateX(0%); opacity: 1; background-color: #f3f9e2;} 
    25%, 45% { transform: translateX(-100%); opacity: 1; background-color: #e0e3e9; } 
    50%, 70% { transform: translateX(-200%); opacity: 1; background-color: #EEF2F5; } 
    75%, 95% { transform: translateX(-300%); opacity: 1; background-color: #faff03; } 
    100%, 120% { transform: translateX(-400%); opacity: 1; background-color: #E1EAF9;}
}
.banner_section .slide_list > li:first-child {
    opacity: 1;
}

.banner_section:hover .slide_list > li {
    animation-play-state: paused;
}
.banner_section .slide_list > li > a {
    display: block;
    position: relative;
}
.banner_section .slide_list > li > a img {
    object-fit: contain;
    width: min-content;
    max-height: 480px;

}
.banner_section .slide_list label {
    position: absolute;
    z-index: 10;
    top: 50%;
    transform: translateY(-50%);
    padding: 50px;
    cursor: pointer;
}

 

 

이를 보완하고자 javascript를 사용하여 코드를 전면 수정하였다

 

수정 후

수정 후 배너 슬라이드

다음과 같이 페이지 네이션이 적용 되었고 왼쪽, 오른쪽 화살표를 사용해 이전 배너 혹은 다음 배너로 이동할 수 있게 되었다~!

 

- html 코드

<section class="banner_section">
                <div class="slide_item item_1" style="background-color: #E1F2FA;">
                    <img src="assets/banner_17.webp">

                </div>
                <div class="slide_item item_2" style="background-color: #40DBFF;">
                    <img src="assets/banner_15.webp">

                </div>
                <div class="slide_item item_3" style="background-color: #D9D8DB;">
                    
                    <img src="assets/banner_18.webp">

                </div>
                <div class="slide_item item_4" style="background-color: #DB0F18;">

                    <img src="assets/banner_20.webp">

                </div>
                ...
                
                <div class="next_btn" id="left"><img src="assets/arrow_left.svg"></div>
                <div class="next_btn" id="right"><img src="assets/arrow_right.svg"></div>
                <ul class="slide_pagination"></ul>
            
                
            </section>

 

-CSS 코드

.banner_section {
    display: flex;
    white-space: nowrap;
    margin : 0 auto;
    overflow: hidden;
    max-width: 100%;
    max-height: 480px;
    position : relative;
}

.slide_item {
    display: flex;
    align-items: center;
    justify-content: center;
    position : relative;
    left: 0;
    width: 100%;
    max-height: 480px;
    flex-shrink: 0;
    transition: left 0.15s;
}

.slide_item > img {
    object-fit: contain;
    width: min-content;
    max-height: 480px;
    overflow: hidden;
}
.next_btn {

    display: flex;
    justify-content: center;
    align-items: center;
    position: absolute;
    top: calc(50% - 16px);
    width: 80px;
    height: 80px;

}
#left {
    left: 0px;
}
#right {
    right: 0px;
}
ul,li {
    list-style-type: none;
    padding: 0;
    margin: 0;
}
.slide_pagination {
    display: flex;
    gap: 5px;
    position: absolute;
    bottom: 0;
    left: 50%;
    transform: translateX(-50%);
}
.slide_pagination > li {
    color: #ffffff88;
    cursor: pointer;
    font-size: 25px;
}
.slide_pagination > li.active{
    color: #ffffff;
    
}

 

- Javascript 코드

const slide = document.querySelector(".banner_section");
let slideWidth = slide.clientWidth;

const leftBtn = document.querySelector("#left");
const rightBtn = document.querySelector("#right");

let slideItems = document.querySelectorAll(".slide_item");
let slideItemsImgs = document.querySelectorAll(".slide_item img");
console.log(slideItems);
const maxSlide = slideItems.length;

let cur = 1;

const pagination = document.querySelector(".slide_pagination");

for(let i=0; i<maxSlide; i++) {
    if(i === 0) pagination.innerHTML += `<li class="active">•</li>`
    else pagination.innerHTML += `<li>•</li>`
}

const paginationItems = document.querySelectorAll(".slide_pagination > li");

const firstSlide = slideItems[0];
const lastSlide = slideItems[slideItems.length-1];

console.log(firstSlide);
const firstEl = document.createElement("div");
const lastEl = document.createElement("div");

lastSlide.classList.forEach(c => lastEl.classList.add(c));
lastEl.innerHTML = lastSlide.innerHTML;

firstSlide.classList.forEach(c => firstEl.classList.add(c));
firstEl.inner
HTML = firstSlide.innerHTML;

slideItems[slideItems.length-1].after(firstEl);

slideItems=document.querySelectorAll(".slide_item");

let offset = slideWidth + cur;
slideItemsImgs.forEach(i => {
    i.setAttribute("style", `left : ${offset}px`);

});




function nextMove() {
    cur++;
    if(cur <= maxSlide) {
        const offset = slideWidth * (cur-1);
        slideItems.forEach(i => {
            i.style.left =  `${-offset}px`;
        
        });
        paginationItems.forEach( i => i.classList.remove("active"));
        paginationItems[cur - 1].classList.add("active");
    }
    else {
        cur = 0;
        let offset = slideWidth * (cur-1);
        slideItems.forEach(i => {
            i.style.left =  `${-offset}px`;
        
        });
        cur++;
        offset = slideWidth * cur;
        setTimeout(() => {
            slideItems.forEach( i => {
                i.style.left =  `${-offset}px`;
            })
        }, 0);
        paginationItems.forEach( i => i.classList.remove("active"));
        paginationItems[cur - 1].classList.add("active");
    }
}
rightBtn.addEventListener("click",nextMove);

function prevMove() {
    cur--;
    if(cur > 0) {
        const offset = slideWidth * cur;
        slideItems.forEach(i => {
            i.style.left =  `${-offset}px`;
        });
        paginationItems.forEach( i => i.classList.remove("active"));
        paginationItems[cur - 1].classList.add("active");
    }
    else {
        cur = maxSlide + 1;
        let offset = slideWidth * cur;
        slideItems.forEach(i => {
            i.style.left =  `${-offset}px`;
        
        });
        cur--;
        offset = slideWidth * cur;
        setTimeout(() => {
            slideItems.forEach( i => {
                i.style.left =  `${-offset}px`;
            });
        }, 0);
        paginationItems.forEach( i => i.classList.remove("active"));
        paginationItems[cur - 1].classList.add("active");
    }

}
leftBtn.addEventListener("click",prevMove);


window.addEventListener("resize", () => {
    slideWidth = slide.clientWidth;
});

for(let i=0; i<maxSlide; i++) {
    paginationItems[i].addEventListener("click" ,() => {
        cur = i+1;
        const offset = slideWidth * cur;
        slideItemsImgs.forEach(i => {
            i.style.left =  `${-offset}px`;
        
        });
        paginationItems.forEach( i => i.classList.remove("active"));
        paginationItems[cur - 1].classList.add("active");

    });
}
let startPoint = 0;
let endPoint = 0;

let loop = setInterval(() => {
    nextMove();
}, 3000);

slide.addEventListener("mouseover", () => {
    clearInterval(loop);
});

slide.addEventListener("mouseout", () => {
    loop = setInterval(() => {
        nextMove();
    }, 3000);
    

})

 

 

 

💣 트러블 슈팅 💣

1.

🙅🏻 이슈  : footer 태그를 사용할 때 footer 요소가 상단 오른쪽으로 붙어버리는 문제 발생

 

➡️ 해결 방법  : 구글링으로 서치해본 결과 footer 내부 요소들이 가벼우면 (?) , 즉 요소들이 많지 않으면.. 종종 footer 태그가 위로 붙어있는 경우가 있다고 한다...(?) 잘 모르겠지만 그냥 body 태그 내에 main과 footer를 전부 감싸주는 div태그를 작성해 주었더니 해결이 되었다..!!

 

2. 

🙅🏻 이슈  : 윈도우 사이즈가 작아지면 가로 스크롤이 생기는 것이 문제였다. 실제 크림사이트를 참고하면 윈도우 사이즈가 작아져도 가로 스크롤은 생기지 않고 최대 넓이가 고정되어있다. 또한 가운데 정렬도 잘 되어있는데 내 코드에서는 그렇지 않고? 요소들이 제각각이였다.

 

➡️ 해결 방법  : max-width와 width : 100%;를 같이 사용한게 화근이였다! 모든 요소들을 상위 div 태그로 감싸주고 하위 태그에 margin : 0 auto로 가운데 정렬 시켜준다.그리고 상위 태그에만 width : 100%를 사용해 주었더니 잘 해결이 되었다.

생각보다 정렬하는게 시간이 많이 잡아먹혔다.... 진짜 똑같이 만들고자 전체 구조를 여러번 갈아엎었더니...생각보다 만만하지 않았다!!!!

 

 

💟 느낀점💟

예전부터 느꼈지만 CSS를 작성하는게 제일 어렵다 ... 매번 공부해도 새롭고 어려운 느낌이였는데 이번 과제를 통해서 flex에 대해 감을 조금 익힌 것 같다!! 그리고 요소들을 다루는 것도 제법 익숙해졌다! 그래도 아직 부족한 점이 많아 더 열심히 찾아보고 공부해야겠다는 생각이 든다!!

728x90