ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Flex Panel Gallery 🎫
    Web/JS30 2020. 9. 21. 18:02
    반응형

    Flex의 여러 속성들을 살펴보고, 직접 다뤄보는 예제였다.

    Flex를 사용하면서도 항상 뭔가 아리송한 점이 많았는데, 조금 정리된 듯한 느낌.

    아직도 헷갈리는 점들이 좀 있기 때문에, 나중에 따로 더 시간을 내서 공부해야 될 것 같다.

    Flex와 Grid는 CSS의 핵심이기 때문에 꼭 시간을 내서 공부를 해야 할 듯.

     

    아래와 같이 5개의 그림이 있는데, 그 중 하나의 패널을 클릭하면 여러 transition이 발생하게끔 해야 했다.

    일단 처음에는 이런 식으로 5개의 패널들이 세로로 나열되어있다.

    <div class="panels">
        <div class="panel panel1">
            <p>Hey</p>
            <p>Let's</p>
            <p>Dance</p>
        </div>
        <div class="panel panel2">
            <p>Give</p>
            <p>Take</p>
            <p>Receive</p>
        </div>
        <div class="panel panel3">
            <p>Experience</p>
            <p>It</p>
            <p>Today</p>
        </div>
        <div class="panel panel4">
            <p>Give</p>
            <p>All</p>
            <p>You can</p>
        </div>
        <div class="panel panel5">
            <p>Life</p>
            <p>In</p>
            <p>Motion</p>
        </div>
    </div>

    이들을 가로로 나열하기 위해서는 container를 flex container로 만들어줘야 한다.

    .panels {
        display : flex;
    }

    그러면, 아래와 같이 변한다.

    이는 flex 아이템의 'flex-basis'라는 속성 때문인데,

    기본값으로 자기가 가진 content의 영역만큼만 자리를 차지하게 되어있기 때문이다.

    저 5개의 패널들이 남은 영역을 골고루 나눠가지게 만들어 주자.

    .panel {
        display : flex;
        flex : 1;
        justify-content : center;
        flex-direction : column;
    }

    일단, panel을 flex container로 만들어 준 이유는

    panel의 내부 요소들도 flex 속성을 이용하여 나열할 것이기 때문.

     

    여기서 'flex'라는 속성이 보이는데, flex 속성flex-grow, flex-shrink. flex-basis를 한 번에 설정할 수 있게 해준다.

    저 3개의 속성은 굉장히 연관 관계가 깊기 때문에, 종종 flex를 사용하여 한 번에 설정하곤 한다.

    a.

    flex-basis아이템이 차지할 기본 영역의 크기를 설정한다.

    flex-basis의 값으로는 우리가 width, height에 사용하는 각종 단위들을 가진 값이 들어갈 수 있다.

    기본값은 auto이며, 해당 아이템의 width값을 사용하게 된다.

    만약 아이템의 기본 width를 따로 설정하지 않으면

    당연히 해당 아이템이 가진 content의 크기만큼 flex-basis가 설정된다.

    참고로, flex-basis에 content라는 값도 있는데, 이는 해당 아이템이 가진 content의 크기를 의미하며

    아이템의 기본 width를 따로 설정하지 않은 경우와 완전히 동일하다.

     

    b.

    flex-shrink는 박스 크기가 유연하게 줄어들도록 할 것인가에 관한 속성.

    flex-basis보다 작아질 수 있는지를 설정한다. 1 이상이면 박스가 유연성을 가져서 flex-basis보다 작아진다.

    기본값은 1. 만약 0으로 세팅하면, 크기가 flex-basis보다 작아지지 않기 때문에

    고정폭을 가진 아이템을 쉽게 만들 수 있다.

     

    c.

    flex-grow는 박스 크기가 유연하게 늘어나도록 할 것인가에 관한 속성.

    아이템들의 기본 flex-basis를 제외한 여백 부분을 flex-grow에 지정된 숫자의 비율만큼 나눠 갖는다.

    기본값은 0이며, 박스 크기가 전혀 늘어나지 않는다.

    참고로, 'flex-basis를 제외한 여백'을 나눈다는 의미이기 때문에 

    만약 아이템들의 flex-grow를 전부 동일하게 1로 설정해도, flex-basis부분은 다를 수 있다는 걸 명심할 것.

    flex-basis말고 나머지 부분이 동일하다는 의미.

     

    그래서 "flex : 1 0 auto;" 라고 하면

    flex-grow는 1, flex-shrink는 0, flex-basis는 auto로 설정하겠다는 의미가 된다.

    위에서 flex : 1이라고 했으니까, flex-grow만 설정되어 모든 panel들이 남은 여백을 골고루 나눠가지게 된다.

    justify-content는 좌우 정렬을 어떻게 할 것인가에 관한 속성.

    flex-direction은 flex 아이템들의 정렬 방향을 의미하므로, panel 내부의 글자들이 세로로 나열된다.

    panel의 내부 요소들도 중앙 정렬을 해준다.

    .panel > * {
        display : flex;
        flex : 1 0 auto;
        align-items : center;
        justify-content : center;
    }

    참고로, 위의 사진은 "flex : 1 0 auto;"를 지정하기 전의 사진. 

    지정하고 난 후에는 위, 중앙, 아래의 글자들이 전부 동일한 영역을 차지해서 글자들이 위 아래로 뚝뚝 떨어지게 된다.

     

    그 다음은 애니메이션을 넣어줄 차례.

    일단 위 아래의 글자들은 transformY를 이용하여 화면 바깥으로 숨길 것이다.

    그리고, 특정 패널을 클릭하면 해당 패널의 크기가 커지면서 위아래에서 글자가 튀어나오게 할 예정.

    그래서, 일단 글자를 숨겨주고, 패널에 'open-active'라는 class가 붙으면 글자가 튀어나오게끔 속성을 붙여준다.

    .panel > *:first-child {
        transform : translateY(-100%);
    }
    
    .panel.open-active > *:first-child {
        transform : translateY(0);
    }
    
    .panel > *:last-child {
        transform : translateY(100%);
    }
    
    .panel.open-active > *:last-child {
        transform : translateY(0);
    }
    
    .panel.open {
        font-size: 40px;
        flex : 5;
    }

    open 클래스가 붙은 패널은 글자 크기가 40px로 커지고, 패널 크기는 5의 비율만큼 커짐.

     

    이제는 자바스크립트로 이벤트 설정을 해 줄 차례.

    const panels = document.querySelectorAll('.panel');
    
    function toggleOpen() {
        this.classList.toggle('open');
    }
    
    function toggleActive(e) {
        if(e.propertyName.includes('flex')) {
            this.classList.toggle('open-active');
        }
    }    
    
    panels.forEach(panel => panel.addEventListener('click', toggleOpen));
    panels.forEach(panel => panel.addEventListener('transitionend', toggleActive));

    일단은 특정 panel을 클릭하면 toggleOpen함수가 실행되도록 하였는데

    toggleOpen함수는 해당 panel에 'open'이라는 클래스를 붙여주는 함수이다.

    만약 addEventListener에서 함수를 붙일 때 toggleOpen()이라고 붙여주게 되면

    '()'는 해당 함수를 바로 실행하겠다는 의미이므로, 페이지가 load될 때 바로 한 번 실행되니까 주의.

     

    그리고 클릭이벤트의 transition(해당 패널이 커지는)이 끝나고 나면

    해당 패널에 'open-active'라는 클래스를 붙여줘야 한다.

    'open-active'는 위에서도 설명했듯이 글자가 튀어나오는 transition을 가진 클래스.

     

    이 때 transitionend 이벤트가 발생하는 요소를 console.log로 찍어보면 다음과 같이 두 개의 요소가 나온다.

    바로 panel의 flex-grow 속성과 자식 요소의 font-size에서 발생하는데,

    우리는 이 중에서 panel을 골라서 이벤트 리스너를 붙여줘야 한다.

     

    참고로, flex-grow 속성은 chrome에서는 flex-grow라는 이름을 가지는데,

    safari에서는 속성 이름이 그냥 'flex'이다.

    그래서, 이 두 경우를 모두 커버해주기 위해 "속성명이 'flex'를 포함하는 요소"를 찾아주면 된다.

    function toggleActive(e) {
        // console.log(e.propertyName);
        if(e.propertyName.includes('flex')) {
            this.classList.toggle('open-active');
        }
    }

    마지막으로, CSS Flexbox를 공부하는 데에 도움이 될 만한 사이트 두 개.

    1. flexbox.io : 지금 내가 공부하고 있는 'Javascript30'과 동일한 방식의 프로젝트.

    하루에 하나씩 flexbox 예제들을 20일동안 공부한다. 물론 한 번에 몰아들어도 되고.

    강의 진행자도 동일한 'Wes Bos'. 나중에 flexbox 공부할 때 한 번 들어봐야 될 듯.

     

    2. 1분코딩 : 1분 코딩에서 포스팅 한 flexbox에 관한 글. 정리를 깔끔하게 잘 해놔서 큰 도움이 된다.

    반응형

    'Web > JS30' 카테고리의 다른 글

    Array Cardio Day 2 🎈  (0) 2020.10.30
    Type Ahead ⌨  (0) 2020.09.25
    Array Cardio Day 1 🎈  (0) 2020.09.21
    Update CSS variables with JS 🎨  (0) 2020.09.20
    CSS + JS Clock ⏱  (0) 2020.09.20

    댓글

Designed by Tistory.