이미지 슬라이드를 반응형으로 짜는 중에 슬라이드 이전 버튼을 클릭할 시 justify-content: flex-end;를 사용하여 정렬을 전환해야 했는데, 기존 코드로는 justify-content: flex-end; 가 작동하지 않았다.
기존 코드↓
<section>
<div>
<ul>
<li style="background-color: red">1</li>
<li style="background-color: orange">2</li>
<li style="background-color: yellow">3</li>
<li style="background-color: green">4</li>
<li style="background-color: blue">5</li>
</ul>
<button class="prev">이전</button>
<button class="next">다음</button>
</div>
</section>
* {
padding: 0;
margin: 0;
}
body {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 100vh;
}
section {
max-width: 400px;
width: 100%;
height: 400px;
}
div {
position: relative;
display: flex;
width: 100%;
height: 100%;
overflow: hidden;
}
ul,
li {
list-style: none;
}
ul {
display: flex;
width: 100%;
height: 100%;
}
li {
flex-shrink: 0;
width: 100%;
height: 100%;
}
button {
position: absolute;
bottom: 0;
}
.prev {
left: 0;
}
.next {
right: 0;
}
const div = document.querySelector('div');
const ul = document.querySelector('ul');
const lis = document.querySelectorAll('li');
const lisCount = lis.length;
const prev = document.querySelector('.prev');
const next = document.querySelector('.next');
let liWidth;
let direction;
let intervalUl;
// set
function setSlide() {
liWidth = lis[0].offsetWidth;
}
setSlide();
// function
function moveUl(direction) {
ul.style.transition = '0.4s';
ul.style.transform = `translateX(${direction * liWidth}px)`;
setTimeout(function(){
if(direction === -1) { //next
ul.appendChild(ul.firstElementChild);
} else if(direction === 1) { //prev
ul.insertBefore(ul.lastElementChild, ul.firstElementChild);
}
ul.style.transition = 'none';
ul.style.transform = `translateX(0px)`;
}, 500);
}
// event
intervalUl = setInterval(function(){
div.style.justifyContent = 'flex-start';
moveUl(-1);
}, 5000);
prev.addEventListener('click', function(){
clearInterval(intervalUl);
div.style.justifyContent = 'flex-end'; // 안 먹는 문제 발생
if(direction === -1) {
ul.appendChild(ul.firstElementChild);
}
direction = 1;
moveUl(direction);
intervalUl = setInterval(function(){
div.style.justifyContent = 'flex-start';
if(direction === 1) {
ul.insertBefore(ul.lastElementChild, ul.firstElementChild);
}
moveUl(-1);
}, 5000);
});
next.addEventListener('click', function(){
clearInterval(intervalUl);
div.style.justifyContent = 'flex-start';
if(direction === 1) {
ul.insertBefore(ul.lastElementChild, ul.firstElementChild);
}
direction = -1;
moveUl(direction);
intervalUl = setInterval(function(){
div.style.justifyContent = 'flex-start';
moveUl(-1);
}, 5000);
});
window.addEventListener('resize', setSlide);
위와 같은 모양의 이미지 슬라이드를 반응형으로 짜려면,
먼저 디바이스의 크기에 맞게 li의 width가 설정되어야 하기 때문에 section에게 max-width 값만 잡아주고 모든 자식 요소들에게 width: 100%로 넣어주었다.
그리고 스크립트 상에서 이미지 슬라이드의 정렬 변경을 위해 div에 justify-content: flex-end; 넣어주었는데, flex-end가 먹지 않는 오류가 생겼다.
justify-content: flex-end; 가 안먹는 상황을 찾아보니 두 가지로 요약할 수 있었다.
- justify-content: flex-end;를 선언한 부모 영역보다 자식들이 커서 여유 공간이 없을 경우
- 자식요소의 영역이 유연하게 변동되어 justify-content: flex-end;를 선언한 부모가 자식의 영역을 파악할 수 없을 경우
나의 문제는 위 상황에서 후자의 경우로,
justify-content: flex-end; 를 먹인 div가 자손 li들의 width 영역을 정확하게 파악할 수 없어서 였다.
때문에 js에서 화면이 resize 되면 justify-content: flex-end;를 먹인 div의 width값을 가져와서 li의 width값으로 고정해주었더니 문제가 해결됐다.
해결된 코드 ↓
const div = document.querySelector('div');
const ul = document.querySelector('ul');
const lis = document.querySelectorAll('li');
const lisCount = lis.length;
const prev = document.querySelector('.prev');
const next = document.querySelector('.next');
let divWidth; // liWidth 를 divWidth로 변경함
let direction;
let intervalUl;
// set
function setSlide() {
// li에게 div의 width 값을 구해서 px로 값을 지정해줌
divWidth = div.offsetWidth;
lis.forEach((item) => {
item.style.width = `${divWidth}px`;
});
}
setSlide();
// function
function moveUl(direction) {
ul.style.transition = '0.4s';
ul.style.transform = `translateX(${direction * divWidth}px)`; // divWidth를 기준으로 이동
setTimeout(function(){
if(direction === -1) { //next
ul.appendChild(ul.firstElementChild);
} else if(direction === 1) { //prev
ul.insertBefore(ul.lastElementChild, ul.firstElementChild);
}
ul.style.transition = 'none';
ul.style.transform = `translateX(0px)`;
}, 500);
}
// event
intervalUl = setInterval(function(){
div.style.justifyContent = 'flex-start';
moveUl(-1);
}, 5000);
prev.addEventListener('click', function(){
clearInterval(intervalUl);
div.style.justifyContent = 'flex-end';
if(direction === -1) {
ul.appendChild(ul.firstElementChild);
}
direction = 1;
moveUl(direction);
intervalUl = setInterval(function(){
div.style.justifyContent = 'flex-start';
if(direction === 1) {
ul.insertBefore(ul.lastElementChild, ul.firstElementChild);
}
moveUl(-1);
}, 5000);
});
next.addEventListener('click', function(){
clearInterval(intervalUl);
div.style.justifyContent = 'flex-start';
if(direction === 1) {
ul.insertBefore(ul.lastElementChild, ul.firstElementChild);
}
direction = -1;
moveUl(direction);
intervalUl = setInterval(function(){
div.style.justifyContent = 'flex-start';
moveUl(-1);
}, 5000);
});
window.addEventListener('resize', setSlide);
안먹는 이유 참고 : https://stackoverflow.com/questions/24052569/the-justify-content-property-isnt-working
'Coding > HTML+CSS' 카테고리의 다른 글
[HTML] SVG 사용하기 (폰트 적용 / 직접 그리기) (0) | 2022.02.14 |
---|---|
[CSS] object-fit로 img 사이즈 맞추기 (0) | 2022.02.07 |
[CSS] img 사이즈 조절 시 흐려지는 현상 (0) | 2021.12.21 |
[CSS] text에 그라데이션 먹이기 (1) | 2021.09.30 |
[CSS] IE에서 flexbox 이미지 버그 해결방법 (0) | 2021.07.07 |