Coding/HTML+CSS

[CSS] justify-content: flex-end 속성이 안 먹는 이유

PSUR 2021. 12. 29. 17:36

이미지 슬라이드를 반응형으로 짜는 중에 슬라이드 이전 버튼을 클릭할 시 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