Css 3) Study

[웹코딩 가이드] 홈

이제 웹 코딩을 배우기 위한 긴 여정을 시작합니다.. diagram-arrow-down

Web 표준html로 웹사이트 틀을 만들고, Css로 꾸며주고, Javascript로 동작시키는데.. 이것들은 각각 분리하여 작성되어야 나중에라도, 누구라도,, 알아보기 쉽고 유지 관리에도 도움이 된다!


이 페이지는 Css 코딩 입문자를 위한 기초 가이드입니다만, html/Css, Javascript 등의 웹 프로그래밍 전반에 걸쳐 본격적으로 학습하고자 한다면; MDN의 문서를 찬찬히 살펴보시기를 권합니다..


Css 3) 필터효과

Css의 속성은 이미지나 배경, 테두리 등에 다양한 효과 함수를 사용하여 블러나 색상 변형 등의 그래픽 효과를 적용한다

필터링: filter
Css의 filter: 필터함수(값); 속성은 요소에 다양한 필터 효과를 적용하는데, 속성값은 공백으로 구분하여 복수의 필터 효과를 조합할 수도 있다: img { filter: grayscale(0.5) blur(10px); }
블러: filter: blur(값);

이 클수록 흐려지는데, 단위는 px을 쓰고, %는 허용되지 않는다!

남산부석 원본 1px 3px
명도: filter: brightness(값);

에는 %(나 소수점 단위)를 쓰는데 0 은 완전히 검게 되며, 100% (= 원본)를 넘으면 더 밝아진다 곧, 100% (및 1) 이하는 원본의 밝기를 낮춘다!

0 50% 남산부석 원본 150%
채도: filter: saturate(값);

에는 %(나 소수점 단위)를 쓰는데 0% 는 완전한 무채색이 되며, 100% (= 원본)를 넘으면 더 채도가 높아진다 곧, 100% (및 1) 이하는 원본의 채도를 낮춘다!

0 50% 남산부석 원본 150%
색상 대비: filter: contrast(값);

0% 는 완전한 회색조이고, 100% 는 원본과 같으며, 그 이상으로 주면 대비가 더 뚜렷해진다 곧, 100% (및 1) 이하는 원본의 색상 대비를 낮춘다!

0 50% 남산부석 원본 150%
그레이스케일 회색조: filter: grayscale(값);

에는 %(나 소수점 단위)를 써서 전환 비율을 지정해주는데 0% (원본 이미지), 100%(완전한 회색조 이미지), 그 사이의 은 회색톤 비율을 지정한다

남산부석 원본 50% 100%
세피아톤 갈색조: filter: sepia(값);

에는 %(나 소수점 단위)를 써서 전환 비율을 지정해주는데 0% (원본 이미지), 100% (완전한 갈색조 이미지), 그 사이의 은 세피아톤 비율을 지정한다

남산부석 원본 50% 100%
색조 회전: filter: hue-rotate(각도값);

주어진 이미지에 hsl 색상환을 적용하는데, 각도값 은 입력 샘플을 조절할 색상환 각도로서 0deg (원본 이미지) ~ 360deg 이다

남산부석 원본 90deg 180deg 270deg
색상 반전: filter: invert(값);

에는 %(나 소수점 단위)를 쓸 수 있는데, 0 (원본 이미지) ~ 1 (정반대 색상으로 반전)까지의 값이 들어간다

남산부석 원본 0.2 0.7 1
불투명도: filter: opacity(값);

주어진 이미지의 불투명도를 설정하는데, 보다 확립된 Css의 opacity 속성과 같은 방식으로 작동한다!

0.1 0.5 0.9 남산부석 원본

* cf) Css 필터는 SVG 이미지에서도 사용할 수 있는데, filter: url(); 함수를 사용하여 연결된 SVG 요소 또는 파일에서 SVG 필터를 적용할 수 있다

                                    
                                        
                                    
                                
백드롭 필터: backdrop-filter
backdrop-filter 속성에서도 Css Filter와 동일한 필터 함수들을 사용하는데, filter 속성이 요소 전체에 필터를 적용하는 반면, 이 속성은 백그라운드에만 필터를 적용한다는 점에서 차이가 있다. 곧, backdrop-filter: 필터링함수[ 필터링함수2, ..]; 속성은 요소 뒤 배경에 블러나 색상 시프트 등의 효과를 준다

공화국을 위하여 !

backdrop titles
                                    
                                        
                                    
                                
                                    
                                        .backdrop_element {
                                            display: flex; flex-direction: column; justify-content: center; align-items: center;
                                            position: relative; width: 100%; height: 50vh; max-height: 150px;
                                        }
                                    
                                        .backdrop_filter {
                                            padding: 0.5em 1em;
                                            backdrop-filter: blur(2px); /* 블러 효과 */
                                            background: rgba(256 256 256 / 0.3); /* 요소 배경에 불투명도를 줌 */
                                            z-index: 1;
                                        }
                                    
                                        .backdrop_element img {
                                            position: absolute; top: 0; left: 0; width: 100%; height: 100%; 
                                            object-fit: cover;
                                        }
                                    
                                

이 효과는 요소의 '뒤'에 적용하기에, 그 효과를 보려면 요소 자체, 또는 요소의 배경에 불투명도를 주어야 한다!

드롭 쉐도우

Css 는 Css의 box-shadow 속성과 다소간 유사하며, 속성값 설정 또한 비슷하다. 하지만, box-shadow 속성이 요소 전체 박스 뒤에 사각형 그림자를 그리는 반면, drop-shadow(); 함수는 이미지 자체의 모양에 맞는 그림자를 만든다는 점에서 차이가 있다!

드롭 쉐도우
Css 3의 filter: drop-shadow(offset-x offset-y [blur] [색상]); 함수는 (박스 뒤에 사각형 그림자를 그리는 것이 아니라)이미지의 배경에, 이미지의 모양에 맞게 흐릿한 블러 효과를 나타내준다 곧, 이미지의 알파 마스크에 흐릿하게 블러 효과를 주어 이미지의 배경으로 합성하는 것이다!
  • offset-x offset-y // 그림자의 가로 세로 오프셋 거리 양수는 우측, 아래쪽 방향이 되고, 음수는 그 반대이다!
  • blur // 이 값(음수는 허용되지 않는다)이 클수록 더 크고 흐린 그림자가 된다 생략하면; 0 으로 설정되어 그림자의 가장자리가 날카로와진다!
  • 색상 // 그림자 색상 미지정 시는 대개 부모요소에 지정된 색상을 상속받는다!

                                    
                                        
                                    
                                
                                    
                                        .d-shadow-ex1 { filter: drop-shadow(-4px -4px grey); }
                                        .d-shadow-ex2 { filter: drop-shadow(4px 4px 2px grey); }
                                    
                                

위 코드의 <i class="bi-alarm"></i> 부분은 부트스트랩의 아이콘을 불러온 것입니다 부트스트랩 아이콘에 관해서는, 나중에 부트스트랩 강좌를 참조하십시오..

블렌딩 모드

Css의 를 이용하면 다수의 레이어에서 색상을 혼합하여 흥미로운 시각적 효과를 낼 수 있고, 이 혼합모드를 활용하여 Css 필터효과나 가상요소 등을 이미지에 적용할 수도 있다!

블렌딩 모드
mix-blend-mode: 키워드; 속성은 대상이 되는 요소의 컨텐츠가 자신의 배경 및 부모요소와 어떻게 혼합되어야할 지를 키워드 값을 통해 지정하는데, 일반 이미지 및 SVG 이미지, 텍스트 모두에서 사용할 수 있다
매화 남산부석
* 이하, 간단한 설명입니다:

* 이하, 간단한 설명입니다:


* cf) 아래는, Multiply가 자신의 배경과 어떻게 혼합되는지 확인해보기 위한 간단한 예제입니다 - 수치로 계산할 수 있는건 아니니 그냥 느낌으로만 이해하십시오 ㅡㅡ;

매화 남산부석
                                            
                                                .blendmode_demo_div {
                                                    max-width: 200px; overflow: hidden;
                                                    background: rgb(218 231 170 / 0.5); /* 이미지가 들어있는 부모요소의 배경색 */
                                                }
                                                
                                                .img_mahwa_multiply, .img_busuk_multiply { mix-blend-mode: normal; }
                                            
                                        

참고로, mix-blend-mode는 요소에 (요소 자신의 배경 및 부모요소 전체와 혼합되는)블렌딩 모드를 적용하는 반면, background-blend-mode는 요소 내부의 배경만을 대상으로 혼합한다!

블렌딩모드의 쌓임맥락
isolation 속성은 z-index의 쌓임 맥락과 유사하게 블렌딩 모드의 새로운 쌓임맥락을 만드는데, mix-blend-mode와 함께 사용할 때 특히 효율적이다 background-blend-mode에서는 (백그라운드 속성은 이미 격리되어 있으므로, 당연히)의미가 없다!
* 시작시, 부모요소의 배경색과 혼합되어 있음! mix-blend-mode: multiply;
                                                    
                                                        
                                                    
                                                
                                                    
                                                        .isolate_demo { /* 부모요소 */
                                                            background: rgb(198, 200, 181);
                                                            max-width: 800px; border: 5px solid gray; border-radius: 0.5rem; overflow: hidden;
                                                        } .isolate_demo img { mix-blend-mode: multiply; } /* 믹스 블렌딩모드 설정 */
                                                    
                                                

부모요소 내부의 이미지들에 mix-blend-mode: multiply;로 주었으므로 처음에는 부모요소의 색상과 혼합되어 나타난다!

                                                    
                                                        const iso_toggle= document.querySelector('#toggle-element3')
                                                        const iso_isolate= document.querySelector('.isolate_img')

                                                        iso_toggle.addEventListener('change', ({target}) => {
                                                            // 박스를 체크하면; isolation 속성값에 isolate를 넣는다
                                                            iso_isolate.style.isolation= target.checked ? 'isolate' : 'auto';
                                                        });
                                                    
                                                

버튼에 체크하면; isolation 속성에 기본값인 auto 대신 isolate 값이 들어간다: isolation: isolate; 이제 내부 이미지들은 부모요소로부터 벗어나 자신만의 쌓임 맥락을 만들게 된다!

                                                    
                                                        
                                                    
                                                
                                                    
                                                        .isolate_ex {
                                                            position: relative;
                                                            isolation: isolate; /* 이 쌓임맥락 격리가 없으면 배경색까지 함께 혼합된다! */
                                                        }
                                                        
                                                        .circle_isolate {
                                                            position: absolute; width: 80px; height: 80px;
                                                            border-radius: 50%;
                                                            mix-blend-mode: screen;
                                                        }
                                                        .circle_isolate-1 { background: red; }
                                                        .circle_isolate-2 { background: green; left: 40px; }
                                                        .circle_isolate-3 { background: blue; left: 20px; top: 40px; }
                                                    
                                                

Css 트랜스폼

Css 은 GPU 가속 속성이므로 일반적으로 전환되며, 더 부드러운 애니메이션을 만든다. 이 속성을 사용하면 임의로 요소의 크기를 조정하거나, 회전 및 기울이기, 이동, 또는 왜곡시킬 수 있다!

트랜스폼: transform
Css transform 속성은 Css 시각적 서식모델의 좌표 공간을 변경하는데, 이는 새로운 쌓임 맥락을 생성한다 !
Transform 1
Transform 2
Transform 3
                                    
                                        
                                    
                                
                                    
                                        .transformed_el1 { transform: translate(30px, 20px) rotate(15deg); }
                                        .transformed_el2 { transform: rotate(90deg); } 
                                        .transformed_el3 { transform: skewx(10deg) translatex(150px); transform-origin: bottom left; } 
                                    
                                

transform-origin 속성으로 원점의 위치를 지정해줄 수 있는데, 생략시의 기본값은 해당 요소의 중심이다!

transform의 지나친 크기 변경/확대/축소 애니메이션은 어떤 사용자에게는 두통을 야기시킬 수도 있다. 이 경우, 미디어 쿼리와 함께 미디어 기능을 이용하면 사용자가 시스템 설정에서 애니메이션을 줄였는지 알아내고, 애니메이션을 비활성화할 수 있다!

rotate(각도deg);는 중심축을 기준으로 각도deg만큼 요소를 회전시키는데, 각각의 축을 기준으로 하는 rotateX/Y/Z(각도deg); 함수를 쓸 수도 있다. 좀 더 복잡하게는; rotate3d(x, y, z, 각도deg);(x, y, z 좌표와 각도) 함수를 쓸 수도 있다: * rotate() 예제

🐶
                                                    
                                                        .transform-rotate {
                                                            animation: rotate 5s ease-in-out both;
                                                        } @keyframes rotate {
                                                            0%   { transform: rotate(0); }
                                                            100% { transform: rotate(180deg); }
                                                        }        
                                                    
                                                

scale(값[, 값2]); 함수는 값[, 값2]만큼 요소를 확대/축소하는데(인수 하나는 x, y 양 방면이며, 인수 둘은 각각 x, y 방면이다), scaleX/Y/Z();scale3d(x, y, z); 함수도 있다: * scaleX/Y() 예제

🐶
                                                    
                                                        .transform-scale {
                                                            animation: scale 5s both;
                                                        } @keyframes scale {
                                                                50% { transform: scale(0.5); }
                                                            100% { transform: scale(1); }
                                                        }
                                                    
                                                

translate(값[, 값2]); 함수는 값[, 값2]만큼(단위는 px, % 등) 요소를 이동시키는데(인수 하나는 x 방면, 인수 둘은 각각 x, y 방면이다), translateX/Y/Z();translate3d(x, y, z); 함수도 있다

🐱
🐶
                                                    
                                                        .transform-translateX {
                                                            animation: slide-in 5s both;
                                                        } @keyframes slide-in {
                                                            0% { transform: translateX(-1000px); }
                                                            100% { transform: translateX(0); }
                                                        }
                                                    
                                                        .transform-translateY {
                                                            animation: slide-down 10s both;
                                                        } @keyframes slide-down {
                                                            0% { transform: translateY(-1000px); }
                                                            100% { transform: translateY(0); }
                                                        }
                                                    
                                                

skew(값[, 값2]); 함수는 값[, 값2]만큼 요소를 비트는데(인수 하나는 x 방면, 인수 둘은 각각 x, y 방면이다), skewX/Y(값); 함수도 있다

🐶
                                                    
                                                        .transform-skew {
                                                            animation: skew 10s both;
                                                        } @keyframes skew {
                                                            0% { transform: skew(0deg, 0deg); }
                                                            50% { transform: skew(45deg, 45deg); }
                                                        }
                                                    
                                                

애니메이션에 Css opacity 속성도 또한 유용하게 사용할 수 있다. 아래는, opacity 속성을 써서 요소의 화면 표시상태를 전환한다

🐶
                                                    
                                                        .animation-opacity {
                                                            animation: opacity 10s both;
                                                        } @keyframes opacity {
                                                            0% { opacity: 1; }
                                                            50% { opacity: 0; }
                                                            100% { opacity: 1; }
                                                        }
                                                    
                                                
➥ 사용자정의 Css) 요소 기울이기

아래 사용자정의 클래스 .rotate-각도.rotate-n-각도 는 해당 각도만큼 요소를 기울인다:

                                    
                                        
                                    
                                
                                    
                                        .rotate-15 { transform: rotate(15deg); }
                                        .rotate-n-15 { transform: rotate(-15deg); }
                                        /* 필요하다면; 같은 방식으로 더 추가해서 사용하면 됩니다 */
                                    
                                
➥ 사용자정의 Css) 컨텐츠 비틀기

.content-skewed 사용자정의 Css를 사용하여 컨텐츠를 비틀 수 있다

.content-skewed 사용자정의 Css를 사용하여 컨텐츠를 비틀 수 있다. 먼저 대상 요소에 .content-skewed content-skewed-right/left 클래스를 추가한 뒤, 내부 자식요소에서 .content-skewed-item 클래스를 사용해주면 된다

                                                    
                                                        
                                                    
                                                
                                                    
                                                        /* --- 컨턴츠 기울이기 --- */
                                                        .content-skewed {
                                                            perspective: 1500px;
                                                            transform-style: preserve-3d;
                                                        }
                
                                                        .content-skewed-right {
                                                            perspective-origin: right center;
                                                        } .content-skewed-right .content-skewed-item {
                                                            transform: rotateY(30deg) rotateX(15deg);
                                                            backface-visibility: hidden;
                                                        }
                
                                                        .content-skewed-left {
                                                            perspective-origin: left center;
                                                        } .content-skewed-left .content-skewed-item {
                                                            transform: rotateY(-30deg) rotateX(15deg);
                                                            backface-visibility: hidden;
                                                        }
                                                    
                                                

Css의 backface-visibility 속성은 3차원으로 움직이는 요소의 뒷면이 사용자를 향할 때 이를 보여줄 지 여부를 지정한다

Css 트랜지션

웹사이트와 상호작용할 때 많은 요소에 중간 상태가 있는 것을 볼 수 있다 - 예컨대, 포커스를 받거나 마우스를 올리면 버튼의 색상이 변경될 수 있는데, Css는 이러한 상태의 스타일을 즉시 전환한다. 이때, Css의 을 사용하면 요소의 초기 상태에서 타겟팅 상태로 부드럽게 전환하도록 중간 단계의 상태를 줄 수 있다. 곧, 두 상태간의 전환 시 시각적 안내나 힌트 등을 제공하여 사용자 환경을 개선할 수 있는 것이다!

트랜지션: transition
트랜지션을 설정하려면; 먼저 transition-property 속성으로 전환하고자 하는 스타일을 지정해주어야 하는데, 쉼표로 구분된 목록 형식의 하나 이상의 Css 속성을 지정해주어야 한다. 그외에도, 아래와 같이 여러 속성값들을 추가적으로 설정해줄 수 있다
  • transition-duration: 전환시간; // 전환이 끝날 때까지의 시간 단위는 s() 및 ms(밀리초)
  • transition-timing-function: ease/ease-in/ease-out/ease-in-out/steps(n)/cubic-bezier(..); // 전환 중, 전환 속도 변경 방식 기본적으로 Css는 속도 변환 없이 일정한 속도로 전환한다(기본값: linear)
  • transition-delay: 대기시간; // 전환이 시작되기 전 대기시간 이 속성은 그룹의 후속 요소들마다 서로 다르게 설정하여 전환을 분산하는 데 유용하다!

transition: 값1 값2[ ..]; 방식으로 일괄 지정해줄 수도 있지만, 이 경우에는 각 항목의 순서에 따르는 움직임들을 고려해야 할 필요성이 생겨나기에.. 더 피곤해집니다 ㅡㅡ;

1. Css 트랜지션을 활성화하려면 Css에 상태 변경 및 해당 상태 변경을 트리거하는 이벤트가 포함되어야 하는데, 보통은 :hover, :focus, :target 등의 의사클래스가 사용되며, 자바스크립트를 쓸 수도 있다:
                                    
                                        
                                    
                                
                                    
                                        .square_hover:hover { transform: scale(1.2); }
                                    
                                
2. 트랜지션에서 Css transform 속성은 GPU 가속 색상이므로 일반적으로 전환되며, 색상(color, background-color, border-color)도 상호작용 시의 상태를 나타내는 좋은 지표가 될 수 있다. Css filter 속성이나 박스 그림자 또한 마우스가 올라간 때의 상태를 나타낼 때 많이 사용된다

🐶 🐱

                                    
                                        
                                    
                                
                                    
                                        .filter_emoji {
                                            filter: grayscale(100%); transition: filter 450ms ease;
                                        } .filter_emoji:is(:hover, :focus) {
                                            filter: grayscale(0%) drop-shadow(0 8px 8px rgb(0 0 0 / 0.5));
                                        }
                                    
                                

* cf) Css 전환을 사용할 때 특정 Css 속성에 트랜지션을 추가하면 성능 문제가 발생할 수도 있다 - 예컨대, widthheitht 값이 변경되면; 페이지의 나머지 부분에서 컨텐츠가 푸시되고, Css는 이에 관련된 주변 모든 요소의 위치를 다시 계산해야 하는 것이다!

                                                    
                                                        
                                                    
                                                
                                                    
                                                        .bubbling_wrapper { display: flex; flex-wrap: wrap; padding: 0; }
                                                        .bubbling {
                                                            width: 75px; height: 75px; margin: 4px; padding: 16px;
                                                            background-color: aquamarine; border-radius: 100%;
                                                            font-size: 2em; text-align: center;
                                                            transition: all 5s ease-in 200ms;
                                                        } .bubbling:is(:hover, :focus) {
                                                            background-color: paleturquoise;
                                                            transform: scale(1.6);
                                                            opacity: 0.6;
                                                            transition: transform 150ms cubic-bezier(0.5, 1.75, 0.75, 1.25);
                                                        }
                                                    
                                                
불국사

눈내린 불국사 - 소산 박대성

                                                    
                                                        
                                                    
                                                
                                                    
                                                        .face_back {
                                                            position: relative; width: 250px; height: 145px;
                                                            transition: transform 3s;
                                                            transform-style: preserve-3d;
                                                        } .face_back:focus, .face_back:hover {
                                                            transform: rotateY(180deg);
                                                        }
                                                        
                                                        .face_ex {
                                                            position: absolute; height: 100%; width: 100%;
                                                            backface-visibility: hidden;
                                                        } .back_ex {
                                                            display: grid; place-items: center;
                                                            background: rgb(113, 157, 238);
                                                            transform: rotateY(180deg);
                                                        }
                                                    
                                                

메뉴 제목

  • html 코드
  • css 스타일
  • js 스크립트
                                                    
                                                        
                                                    
                                                
                                                    
                                                        .sliding-menu { position: relative; overflow: hidden; }

                                                        .sliding-actions { /* 메뉴 숨김으로 시작한다 */
                                                            position: absolute; top: 0; right: 0; width: 300px; height: auto;
                                                            padding: 2em; border: grey solid 5px; background: rgb(182 189 166 / 0.5);
                                                            float: right;
                                                            transform: translateX(calc(300px + 4em +  10px)); /* 메뉴 너비 + 양쪽 패딩 + 양쪽 테두리 */
                                                            transition: all 500ms linear; /* 트랜지션(전환) 효과 */
                                                        } .sliding-actions.display { /* 메뉴 펼치기 */
                                                            transform: translateX(0);
                                                            transition: all 1000ms linear; /* 같은 값으로 설정한다면; 생략해도 된다! */
                                                            z-index: 1; /* 메뉴가 본문 내용의 위로 올라오도록 한다 */
                                                        }
                                                    
                                                
                                                    
                                                        const sidebar= document.getElementById('sliding-sidebar');

                                                        document.getElementById('sliding-show').addEventListener('click', () => {
                                                            sidebar.classList.toggle('display');
                                                        });
                                                    
                                                

@keyframes

일반적으로 애니메이션의 키프레임은 타임라인의 타임 스텝에 애니메이션의 상태를 할당하는 데 사용하는 메커니즘으로서, 시작과 종료 및 중간 지점들로 이루어진다. Css의 에서의 @keyframes 또한 애니메이션의 키프레임과 동일한 개념을 기반으로 한다

키프레임: @keyframes
Css에서 @keyframes를 사용하려면 다양한 애니메이션 속성을 개별적으로 정의하거나, animation 속성으로 일괄 설정해줄 수도 있다. 아래 코드는 여러 상태가 있는 키프레임을 정의한 것인데, 여기서 키프레임 이름(my-animation)은 함수 이름처럼 작동하여 Css 코드의 다른 위치에서 이를 참조할 수 있게 된다
[ @keyframes 정의 ]
                                        
                                            @keyframes my-animation { /* 키프레임 이름 */
                                                  0% { transform: translateY(20px); /* 키프레임의 시작 지점 ← 키워드 from과 같다 */ }
                                                 50% { transform: translateY(10px); }
                                                100% { transform: translateY(0px); /* 키프레임의 끝 지점 ← 키워드 to와 같다 */ }
                                            }
                                        
                                    
  • animation-duration: 지속시간; @keyframes 타임라인의 길이(딘위: sms)
  • animation-delay: 대기시간; 애니메이션이 시작되기 전 대기시간
  • animation-direction: reverse/alternate/alternate-reverse; 타임라인의 진행 방향
  • animation-iteration-count: 횟수; 타임라인의 반복횟수 (기본값: 1) 애니메이션 루프를 만들려면; infinite 값을 주면 된다!
                                                    
                                                        
                                                    
                                                
                                                    
                                                        .demo_step {
                                                            animation: move; /* 키프레임 이름 */
                                                            animation-delay: 3s; /* 시작 전 대기시간 */
                                                            animation-duration: 10s; /* 애니메이션 길이 */
                                                            animation-iteration-count: infinite; /* 반복횟수 ← 기본값 1 */
                                                        } @keyframes move { /* 키프레임 */
                                                              0% { transform: translateX(0px); }
                                                            100% { transform: translateX(400px); }
                                                        }
                                                    
                                                        .demo_step {
                                                            width: 50px; height: 50px; background: rgb(138, 156, 123);
                                                        } .demo_step:hover { animation-play-state: paused; cursor: wait; } /* 일시 정지 */
                                                    
                                                

animation-play-state: paused;는 애니메이션을 일시 중지시킨다

                                                    
                                                        const toggle_el= document.querySelector('#toggle-ele');
                                                        const demo_steps= document.querySelector('.demo_step');
                                                    
                                                        toggle_el.addEventListener('change', ({ target }) => {
                                                            demo_steps.style.animationTimingFunction= target.checked ? 'steps(5)' : 'linear';
                                                        });
                                                    
                                                

선을 따라 이동하는 대신 간격을 두고 이동하여 애니메이션을 더 세부적으로 제어하고 싶다면; animation-Timing-Function 속성값에 steps(단계수); 함수를 써서 타임라인을 동일한 길이의 정의된 간격으로 나누어줄 수 있다!


각 타이밍 함수 키워드(예: ease)는 사전 정의된 Bézier 곡선을 사용하여 계산되는데, Css에서는 cubic-bezier(x1, y1, x2, y2); 함수를 사용하여 베지어 곡선을 직접 정의해줄 수도 있다 이 베지어 곡선을 이해하는 것은 매우 어려우므로 같은 사이트가 도움이 될 수 있습니다. 나아가, 다양한 Css 애니메이션들을 만들어주는 사이트도 이용해보십시오..

Css 베이직 쉐이프

Css 데이터 유형은 clip-pathshape-outside 속성에서 사용되는 모양으로서, Css 박스모델 개념을 상속하지만, 이는 Shape 요소 자신의 외부에 적용되는 것이고, 이를 통해 주변 요소의 위치를 재설정해줄 수 있게된다!

쉐이프 도형 작성하기
쉐이프 도형을 만들 때 기본 참조상자는 basic-shape 데이터 타입에 사용하는 속성들에 의해 정의되는데, 쉐이프의 좌표계는 기본적으로 참조박스의 좌상단 모서리가 원점이 되며, x축은 오른쪽으로, y축은 아래쪽으로 진행된다
clip-path 속성: 요소 자신의 클리핑 범위를 지정하는데, 클리핑 범위 안의 부분은 보여지고, 바깥은 숨겨진다
192x192 크기의 정사각 이미지 192x192 크기의 정사각 이미지
                                    
                                        
                                    
                                
                                    
                                        .shape_box { /* 기준이 되는 참조 박스 */
                                            max-width: 600px; margin: 0 auto;
                                        }
                                        
                                        .shape_box img.image1 { clip-path: inset(0 round 10%); } /* 둥근 모서리 */
                                        .shape_box img.image2 { clip-path: circle(); } /* 원 */
                                    
                                

쉐이프 함수의 인수값 중 %로 표시되는 모든 길이는 참조상자의 크기에 의해(그에 대비한 비율로) 결정된다!

shape-outside 속성: 인접한 인라인 컨텐츠가 줄바꿈되어야 하는 모양(사각형이 아닐 수 있음)을 정의한다 - 곧, 인라인 컨텐츠는 기본적으로 요소 주위에서 사각형 형태로 배치되지만, shape-outside 속성을 써서 주변의 인라인 컨텐츠가 (박스모델의 사각형이 아니라)요소의 곡선을 따라 둘러싸도록 할 수 있는 것이다

shape-outside: circle() padding/border/margin-box; 쉐이프 요소와 주변 요소 사이의 간격을 설정한다

                                                    
                                                        
                                                    
                                                
                                                    
                                                        .main_shapefnc {
                                                            width: 550px; margin: 0 auto;
                                                            display: flow-root; /* 내부 플로팅 요소들의 플로팅 해제용 */
                                                        } .left_shapefnc, .right_shapefnc {
                                                            height: 13ex; width: 40%; background-color: lightgray;
                                                        } .left_shapefnc {
                                                            clip-path: polygon(0 0, 100% 100%, 0 100%);
                                                            shape-outside: polygon(0 0, 100% 100%, 0 100%);
                                                            float: left;
                                                        } .right_shapefnc {
                                                            clip-path: polygon(100% 0, 100% 100%, 0 100%);
                                                            shape-outside: polygon(100% 0, 100% 100%, 0 100%);
                                                            float: right;
                                                        }
                                                    
                                                

Shape 요소에서 shape-outside: circle() padding-box; 값을 주면; 주변 요소는 이 Shape 원의 마진(기본값) 및 테두리 영역을 넘어 곧바로 패딩 영역에 달라붙게 된다!

쉐이프 레이아웃
1. 아래는 Css 플로팅에 의해 이미지와 텍스트가 좌우로 배치될 때의 기본 형태이다

문단 옆에 원을 그려주고, Css 플로팅으로 좌우로 배치해봤는데.. 이 원은 Css 박스모델의 사각형 모양 그대로 문단 옆 사각 박스 영역만큼을 차지하면서 자리잡고 있군요 ㅡㅡ; 이 문단이 원을 따라서 둥글게 자리잡도록 할 수 있는 방법은 없을까요?

                                    
                                        
                                    
                                
                                    
                                        .s_circle { 
                                            width: 100px; height: 100px; border-radius: 50%; background-color: #77b597;
                                            float: left;
                                        }
                                    
                                
2. Css 쉐이프 도형(및 쉐이프 함수)를 사용하면 박스모델의 단순한 사각형을 넘어, 주변 요소와의 관계에서 보다 추상적이고 기하학적인 레이아웃을 만들 수 있다

circle(); 함수는 원을 그려주는데, 그 원에다 shape-outside: circle(); 속성을 추가하여 주변 인라인 요소가 원형에 맞춰 줄바꿈되도록 했습니다, 화려한 변신이군요 ^^ shape-outside 속성은 인라인 컨텐츠가 박스모델이 아닌 주변 요소의 곡선을 따라 둘러싸도록 합니다. 추가적으로, 위 원에다 마진을 약간 주니 보기에 더 좋군요: margin-right: 1em; 값으로 주변 요소들과의 사이에 약간의 간격을 줬습니다..

                                    
                                        
                                    
                                
                                    
                                        .s_circle2 {
                                            shape-outside: circle(); /* 바깥쪽 경계 모양 설정 */
                                            margin-right: 1em; /* 원 주변 요소와의 마진 간격 */
                                        }
                                    
                                

원을 그려주는 circle([r at x y]); 함수는 (요소 박스의 좌상단을 기준으로 하는)x, y 중점 좌표(생략 시, 요소 박스 정중앙인 50% 50% 이다)에서 시작되는 (요소 크기에 대비한)반지름 r 의 크기(생략 시, 원 지름은 요소 박스 전체 크기가 된다)에 의해 규정된다 단위로는 px, %, top/bottom/left/right/center, closest-side/farthest-side 등을 사용할 수 있는데, 원의 크기를 (줄이거나 늘여서)값으로 넣어줄 때는 circle(50px at 30% 70%);(= 원 중심은 박스의 30% 70% 지점이 되고, 원의 지름은 100px 크기가 된다) 식으로 r 값과 x y 값을 함께 넣어주어야 한다!

쉐이프 함수

Css의 clip-pathshape-outside 속성들은 도형을 사용하여 상자를 시각적으로 자르거나 컨텐츠가 흐를 도형을 작성하는데, inset();, circle();, ellipse();, polygon(); 등의 간단한 도형 작성 관련 함수들이나, 좀 더 복잡한 path(); 함수를 써서 정의해줄 수 있다

쉐이프 함수: rect();, circle();
rect(); 함수는 컨테이너 박스의 좌상단 원점으로부터 지정된 거리에 사각형을 정의하며, circle(); 함수는 반지름과 위치를 이용하여 원 도형을 정의한다: circle(50px at 30% 70%);
남산부석

rect(); 함수는 컨테이너 박스의 좌상단 원점으로부터 지정된 거리에 사각형을 정의하며, circle(); 함수는 반지름과 위치를 이용하여 원 도형을 정의한다j: circle(50px at 30% 70%);

남산부석

rect(); 함수는 컨테이너 박스의 좌상단 원점으로부터 지정된 거리에 사각형을 정의하며, circle(); 함수는 반지름과 위치를 이용하여 원 도형을 정의한다: circle(50px at 30% 70%);

한편, ellipse(); 함수는 (타원이므로)두 개의 반지름을 지정해야 한다는 점을 제외하고는 circle(); 함수와 매우 유사한 방식으로 작동한다: ellipse(100px 200px at 10% 20%);

                                    
                                        
                                    
                                
                                    
                                        .shape_rect, .shape_circle, .shape_ellipse {
                                            max-width: 800px; margin: 0 auto; display: flow-root; /* 플로팅 해제용 */
                                        }
                                        
                                        .shape_rect img {
                                            float: left; margin-right: 1.5em;
                                            clip-path: rect(); /* 쉐이프 사각형 */
                                            shape-outside: rect(); /* 사각형 옆 문단 */
                                        }

                                        .shape_circle img {
                                            float: left; margin-right: 1.5em; margin-top: 1em;
                                            clip-path: circle(); /* 쉐이프 원 */
                                            shape-outside: circle(); /* 원 옆 문단 */
                                        }
                                    
                                

polygon(); 함수는 SVG 채우기 규칙과 위치값을 써서 다각형을 정의하는데, 이 함수는 직접 작성하기에는 좀 어려우니, 필요하다면; 같은 폴리곤 자동 변환 사이트를 이용해보십시오..

쉐이프 함수: inset();
inset(값 값 값 값 [round 값]); 함수는 박스의 각 측면에서 지정된 인셋 거리에 사각형을 정의한다
앞쪽 인수는 상자 안쪽으로 상/우/하/좌로부터의 인셋 거리이며(인수의 개수는 3, 2, 1의 단축값으로 줄 수도 있다), 추가 옵션인 round 값(값은 1, 2, 3, 4개까지 줄 수 있다) 인수는 박스 코너(좌상, 우상, 우하, 좌하 순서임) 둥근 모서리를 설정한다 단위는 px% 모두 가능하다
                                    
                                        
                                    
                                
                                    
                                        .shape_inset {
                                            width: 150px; height: 80px; margin: 10px 10px 10px 40px; background-color: coral; float: left;
                                            clip-path: inset(30px 60px 15px 0 round 25px);
                                            shape-outside: inset(40px 40px 10px 0 round 15px);
                                        }
                                    
                                
offset-path: xywh(x y w h); 속성은 참조 상자의 x, y 방면 거리와 해당 지점에서의 w, h 값(너비 높이)을 설정하여 사각 박스 영역을 설정해준다. 추가적으로, clip-path 속성으로 클리핑 경로를 정의해줄 수 있다
음~ 좀 어렵군요.. 너무 어려우니 대충, 대충,, 코드 만지작, 만지작 하면서 확인해 보십시오.. 덕분에, 이 세상 누구도 못 본 그 난해한 양자 도약을 눈으로 직접 구경하게 되는군요, 봤나요? 못 봤나요??
                                                
                                                    
                                                
                                            
                                                
                                                    .xywh_path {
                                                        width: 25px; height: 25px;
                                                        background-color: rgb(140, 196, 106);
                                                        animation: move 20s linear infinite;
                                                    } @keyframes move {
                                                          0% { offset-distance: 25%; }
                                                        100% { offset-distance: 100%; }
                                                    }
                                                    
                                                    .xywh-path_sub {
                                                        offset-path: xywh(0px 0px 100% 100% round 10%);
                                                        clip-path: circle();
                                                    }
                                                
                                            

스크롤 Overflow

Css 오버스크롤 동작 모듈은 스크롤 위치가 '스크롤 경계'에 도달할 때(이 경계를 넘는 오버스크롤 시) 스크롤 컨테이너의 동작을 제어한다

스크롤 오버플로우
요소의 내용이 컨테이너보다 크고, 스크롤이 가능하거나 기본적으로 스크롤되는 상황에서(예컨대, 블로그 게시판에서 [게시글] 입력 시) 요소의 스크롤 가능 영역을 지나 계속해서 스크롤하면 부모요소에서 스크롤이 시작되는 경우가 있다. 반대로, 웹사이트의 이용약관에서 보듯이, [확인란]을 활성화하기 위해 약관 설명 바깥까지 도달하더라도 페이지가 스크롤되거나 바운스되지 않도록 할 수도 있다
                                    
                                        #chat-board .messags {
                                            height: 300px;
                                            overflow: auto; overscroll-behavior: contain;
                                        }
                                    
                                

이 코드는 채팅창의 스크롤 컨텍스트와 기본 페이지를 논리적으로 분리하고, 그리하여 페이지 하단에 고정된 채팅창의 맨 밑 게시물까지 스크롤해 내려가도 기본 페이지로 스크롤이 전파되는 것을 막아준다!

1. 기본적으로, 컨테이너(또는, 페이지 자체)에서 발생한 스크롤은 끝 경계 지점까지 도달하여 오버스크롤될 때 상위요소로 전파될 수 있는데(기본값인 auto), overscroll-behavior 속성에 contain 값을 주어 상위요소로의 스크롤 체이닝 전파를 막고, 나아가 모바일앱에서의 스크롤하여 새로고침 작업도 중단시킬 수 있다. 한편, none 값은 contain과 동일하지만 Android의 오버스크롤 글로우 효과 및 iOS의 리버밴딩 효과 까지 방지한다:

* cf) 참고로, 스크롤하여 새로고침 작업을 사용 중지하는 것은 전체 뷰포트 정의 요소(대개, <html> 또는 <body>)에서 스크롤 체이닝을 방지하기만 하면 된다(body { overscroll-behavior-y: contain; }). 한편, '스크롤 경계'에 도달할 때의 반동 효과(= 오버스크롤 글로우 효과리버밴딩 효과) 까지 사용 중지하고자 한다면; body { overscroll-behavior-y: none; } 코드를 사용하면 된다 이 경우, 좌/우측 스와이프 탐색은 계속 유지된다!

2. scroll-behavior 속성을 사용하면 요소에 대한 브라우저 제어 스크롤을 선택할 수 있고, scrollTo(); 또는 링크와 같은 페이지 내부 탐색 방법을 지정할 수 있는데, 이 모드는 prefers-reduced-motion과 함께 사용하여 사용자 환경설정에 따라 스크롤 동작을 지정하는 경우에 특히 유용하다!
3. 모바일 앱에서 일부 스크롤러에 절대적 스크롤러(= 풀-투-리프레시) 동작이 있는데, 이는 Root Scroller에서 발생한다. 한 페이지에는 루트 스크롤러가 단 하나만 존재하며, 기본적으로 documentElement는 페이지의 루트 스크롤러이지만, 이 루트 스크롤러를 변경하면; 특정 동작이 documentElement 이외의 스크롤러에도 적용될 수 있다(= 암시적 루트 스크롤러)
[ 암시적 루트 스크롤러 ]
                                        
                                            const rootElement= document.documentElement
                                            const firstTier= rootElement.childNodes
                                            // firstTier는 루트 요소의 직계 자식의 NodeList(head, body 등)이다
                                            
                                            for(const child of firstTier) {
                                              // 루트 요소의 각 직계 자식으로 작업한다..
                                            }
                                        
                                    

암시적 루트 스크롤러를 만들려면; 컨테이너를 고정으로 배치하여 전체 표시 영역을 덮고, 스크롤러와 함께 z-index가 가장 높은지 확인하는 스크롤러 승격을 사용하면 된다!

스크롤 스냅

Css 스크롤 스냅은 스크롤 작업이 완료된 후 스크롤 컨테이너의 스크롤 오프셋을 원하는 스냅 위치가 되도록 조정하는 작업으로서, 이를 이용하면 페이지 매김된 기사나 캐러셀 이미지 등에서 스크롤 스냅 위치를 선언하여 잘 제어된 부드러운 스크롤 환경을 만들 수 있다!

스크롤 스냅 활성화하기
1. 스크롤 스냅을 활성화하기 위해서는; 먼저, 스크롤 컨테이너의 크기와 overflow 속성을 정의해주어야 한다. 다음, 스크롤 컨테이너에서 scroll-snap-type: x/y/both;(스크롤이 발생하는 축) 속성을 주어 스크롤 스냅을 활성화하는데, mandatoryproximity 옵션(맞춤의 엄격도)을 추가해줄 수도 있다:
  • mandatory 옵션은 컨텐츠가 어느 지점에 스냅되건 간에 스크롤과 상관없음을 브라우저에 알려준다 이는 스크롤이 완료될 때, 화면 상단에 있을 것으로 예상하는 것이 분명 거기에 있을 것이라고 확신할 수 있으므로 일관된 스크롤링이 가능해진다!
  • proximity 옵션은 근처에 있을 때만 스크롤 컨텐츠를 해당 위치에 스냅하며, 정확한 거리는 브라우저가 결정하도록 한다
[ 스크롤 스냅 활성화 ]
                                        
                                            .scroll_container { /* 스크롤 컨테이너 */
                                                height: 400px;
                                                overflow-y: scroll;
                                                scroll-snap-type: y mandatory;
                                            }
                                        
                                    

이 코드에서 height: 400px;overflow-y: scroll; 값은 스크롤 컨테이너에 설정하는데, 컨텐츠가 컨테이너를 넘치지 않는다면; 스크롤할 것은 없다!

2-1. 이어서, 스크롤 컨테이너의 하위 컨텐츠 요소에서 scroll-snap-align: start/center/end; 선언으로 스크롤 컨테이너 스냅 포트의 스크롤 오프셋(= 컨텐츠 정렬 위치)를 설정해준다:
[ 스크롤할 컨텐츠 ]
                                        
                                            .scroll_container div { /* 스크롤할 컨텐츠 */
                                                scroll-snap-align: start; /* 블록축과 인라인축 모두에 적용된다 */
                                                /* scroll-snap-align: start center; 식으로 두개의 값을 주면; 각각 블록축과 인라인축에 적용된다 */
                                            }
                                        
                                    

스냅 포트 표시 영역은 스크롤 컨테이너의 시각적 표시 영역과 동일하지만 scroll-padding 속성을 사용하여 조정해줄 수도 있다!


* cf) 자식 요소 중 하나의 컨텐츠가 부모 컨테이너를 넘칠 경우라면; mandatory 옵션을 사용해서는 안된다 - 이 경우, 사용자가 넘친 컨텐츠를 스크롤하여 볼 수 없게된다! 또한, scroll-snap-type 값이 mandatory이면서 자식 요소의 scroll-snap-align 값이 없거나 none(기본값임!)이라면; 사용자는 해당 요소를 스크롤하여 볼 수 없다!

2-2. 스크롤 스냅에서 scroll-snap-align 값이 startend일 때, 스크롤 컨텐츠가 스냅 포트의 가장자리에 딱 붙지 않게 하려면; 스크롤 컨테이너에서 scroll-padding 값(= 인셋)을 설정해주면 된다. 나아가, 각 스크롤 컨텐츠 요소에서 scroll-margin 값(= 아웃셋)을 설정해줄 수도 있다:

스티키 헤더

div 1

div 2

div 3

div 4

div 5

div 6

div 7

div 8

div 9

                                                    
                                                        
                                                    
                                                
                                                    
                                                        /* 스크롤 패딩과 마진 */
                                                        .scroll_container { /* 스크롤 컨테이너 */
                                                            height: 400px;
                                                            overflow-y: scroll;
                                                            scroll-snap-type: y mandatory;
                                                            scroll-padding: 30px; /* 스크롤 컨테이너에서, 스크롤 패딩 설정 */
                                                        }
                                                        
                                                        .scroll_container div { /* 스크롤 컨텐츠 요소들 */
                                                            scroll-snap-align: start;
                                                            scroll-margin: 10px; /* 각 스크롤 컨텐츠에서, 스크롤 마진 설정 */
                                                        }
                                                        
                                                        .positioned-sticky { /* 상단 스키티 요소 */
                                                            position: sticky; top: 0px;
                                                        }
                                                    
                                                

상단에 스티키와 같은 고정된 요소가 배치되어 있는 경우 스크롤된 컨텐츠와 겹칠 수 있는데, 이런 때 scroll-padding을 사용하면 스티키 요소를 위한 공간을 마련해줄 수 있다 - 이 패딩이 없다면; 스크롤 스냅이 발생할 때 고정된 스티키 요소가 일부 컨텐츠와 겹치게 된다!


다시 말해, scroll-padding 속성은 스크롤 컨테이너(또는, 스냅포트)의 표시영역을 조정하는 데 사용되는 스크롤 컨테이너의 인셋을 정의하며, scroll-margin 속성은 스크롤 컨테이너(또는, 스냅포트)의 대상이 되는 각 스크롤 컨텐츠 요소간 마진 간격을 조정하는 데 사용할 오프셋을 정의한다 이러한 스크롤 컨테이너의 패딩과 스크롤 대상요소의 마진은 단순히 스크롤 표시영역을 맞추는 것이 아니라, 모든 관련 스크롤 작업 컨테이너 및 대상 컨텐츠 요소의 크기를 실제로 수정한다!

3. 기본적으로 스크롤 스냅은 사용자가 스크롤을 멈췄을 때만 작동한다. 따라서, 그 전에 여러 스냅 지점을 건너뛰어 지나칠 가능성이 있는데, 스크롤 대상요소에 scroll-snap-stop: always; 값을 주면; 이 건너뜀을 막을 수 있다:
[ 스냅 지점 건너뜀 방지 ]
                                        
                                            .scroll-container {
                                                scroll-snap-type: x mandatory;
                                            }
                                            
                                            .scroll-container > div { /* div:nth-of-type(odd) 및 div:nth-of-type(even) 식으로 좀 더 복잡하게 설정하는 것도 가능하다 ← 홀수번째 및 짝수번째마다 */
                                                scroll-snap-align: center;
                                                scroll-snap-stop: always; /* scroll-snap-stop: normal; ← 기본값 */
                                            }
                                        
                                    

이 효과는 scroll-snap-type 속성에 mandatory 값이 주어졌을 때 더 두드러진다!

스크롤 스냅 활용 사례
1. 스크롤 스냅을 활용하는 가장 일반적인 사례로는 가로 이미지 캐러셀이 있다. 가로축에 scroll-snap-type이 있도록 스크롤 컨테이너를 지정해주고, scroll-snap-align 속성으로 각 이미지의 맞춤 위치를 설정해주면 된다:
[ 가로 스크롤 스냅 ]
                                        
                                            
                                        
                                    
                                        
                                            #gallery {
                                                display: flex;
                                                overflow-x: scroll;
                                                scroll-snap-type: x mandatory;
                                                scroll-padding: 50%; /* 자식요소들을 컨테이너 중앙에 스냅되도록 한다 */
                                            } #gallery img { scroll-snap-align: center; }
                                        
                                    
2. 스크롤 스냅을 활용하는 또 다른 대표적 사례는 세로로 스크롤할 수 있는 논리적 섹션들이 있는 페이지인데, 이 경우에는 scroll-snap-type: y proximity;가 더 적합하다 - 이는 사용자가 특정 섹션의 중앙으로 스크롤할 때 간섭을 일으키지 않으며, 사용자가 충분히 가까이 스크롤하면 스냅된다:
[ 세로 스크롤 스냅 ]
                                        
                                            
                                        
                                    
                                        
                                            header { position: fixed; height: 10vh; }
    
                                            section {
                                                scroll-snap-type: y proximity;
                                                overflow-y: scroll;
                                                scroll-padding-top: 15vh; /* 헤더 및 그밖의 추가 확장 공간을 위한 여분! */
                                            } article { scroll-snap-align: start; }
                                        
                                    

스크롤 컨테이너의 상단에 15vh 인셋을 추가해줌으로써(scroll-padding-top: 15vh;), 웹브라우저에게 스크롤 컨테이너의 상단에서 15vh 아래 지점을 스크롤 스냅의 세로 시작 지점으로 취급하라고 알려주고, 따라서 스크롤 맞춤 대상요소의 시작 지점이 이 새로운 위치와 함께 플러시되어 위로 그만큼의 공간이 여분으로 확보된다!

3. (전체화면 섹션들로 구성된 개인 블로그 등) 및 (전체화면 이미지들로 구성된 캐러셀 이미지 슬라이더 등)도 웹사이트를 돌아다니면서 자주 접하게 되는 풍경들이다. 한편, 동시에 x, y 양방향으로 스크롤 스냅을 작동시킬 수도 있다 - 예컨대, 작은 타일들로 구성된 2차원 썸네일 갤러리를 구성할 때인데, 아래와 같은 방식으로 스크롤 스냅을 위한 Css 코드를 작성해줄 수 있다:
[ 양방향 스크롤 스냅 ]
                                        
                                            .thumbnail-gallery { /* 썸네일 갤러리 컨테이너 */
                                                height: 90vh;
                                                overflow: scroll;
                                                scroll-snap-type: both mandatory; /* 상하, 좌우 양방향 스크롤 스냅 타입 설정 */
                                            } .tile { /* 각각의 썸네일 이미지들 */
                                                scroll-snap-align: start;
                                            }
                                        
                                    

이상, 이래 저래 스크롤 스냅 관련 요점들을 정리해봤지만.. 꽤나 어려운데다, 최신 기법이라 브라우저별 호환성 문제나 기기별 정상작동 여부는 MDN의 브라우저 호환성 명세도 참조하면서, 코딩 시 직접 확인해봐야 할 듯합니다 ㅡㅡ;

wave