Css 3) 3

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

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

우선.. 이 Web 코딩 강좌는 html 5Css 3, Bootstrap 5에 의거하여(추가적으로, 약간의 자바스크립트 코드도 가미하고, 외부 플러그인 라이브러리들도 좀 써서) 작성되었음을 알리며 문을 엽니다 - 곧, 이 웹사이트의 모든 모양과 움직임, 다양한 효과 등은 다 그 자체로 이 강좌에 나오는 내용들을 바탕으로 해서 작성된 것입니다!

Backgrounds

모든 Css 박스 뒤에는 배경 레이어라고 하는 특수 레이어가 존재하는데, 이 배경은 사용자의 시야로부터 가장 먼 곳에 위치하며 패딩 영역에서부터 시작하는 컨텐츠의 뒤에서 렌더링된다!

배경색과 배경 이미지: background-color, background-image
배경색은 필요시 원하는 요소에서 각각 따로 지정해주어야 하는데, 배경에 설정하는 색상은 (패딩 영역에서 시작하여 컨텐츠 영역까지에 걸쳐)해당 요소 뒤에서 보여진다:

블록레벨 요소 <p>의 배경색 대 인라인 요소 <span>의 배경색

                                    
                                        
                                    
                                
배경 이미지는 배경색 위에 배치되며(배경색을 가린다!), 테두리에 의해 가려지게 된다. ,로 구분하여 다수의 url("이미지"), url("이미지2"), .. 식으로 배경 이미지를 복수로 지정해줄 수도 있다 - 이 경우, 나중에 나오는 이미지가 위쪽으로 겹쳐지면서 쌓인다. 또한, 배경 이미지에는 url("이미지")만 아니라 그라디언트 배경도 넣어줄 수 있다!

블록레벨 요소 <p>의 배경색과 배경 이미지

                                    
                                        
                                    
                                

지정한 이미지가 불투명해서 아래의 배경색이 나타나지 않을지라도, 배경색을 함께 지정해주는 것이 좋다 - 이미지를 불러올 수 없는 상황에서 배경색이 이미지를 대체할 수 있기 때문이다!

배경 이미지의 반복: background-repeat
배경 이미지의 크기가 배경을 채우려는 요소보다 작은 경우; 기본적으로는 가로/세로로 반복해서 채워지는데(기본값: repeat), background-repeat 속성에 round 값을 주어 이미지가 잘리지 않게 크기를 조절하여 반복하거나, space 값을 주어 끝에서 끝까지 고르게 분배해줄 수도 있다. 또는, background-repeat: repeat-x/y; 값을 주어 원하는 반복 방향을 지정해주거나 no-repeat 값을 주어 반복하지 않도록 설정해줄 수도 있다:

배경 이미지 반복 예)

배경 이미지 위치 지정하기: background-position
background-position: x, y;(콤마로 구분된 하나 이상의 값이 들어간다) 속성으로 배경 이미지 배치의 시작 지점을 설정해줄 수 있다. 으로는 키워드(top/right/bottom/leftcenter)나 px, %를 쓸 수 있는데, 키워드와 숫자 등을 혼합하여 쓸 수도 있다 기본값은 좌상단 모서리인 0, 0(= left top)인데, 양수는 오른쪽 및 아래쪽 방향이 되며, 음수는 그 반대 방향이 된다!

background-image: url("_images/블렌딩모드-매화.jpg"); background-color: #d1e2f0;
background-position: right bottom; background-repeat: no-repeat;

이 위치 지정 방식은 상당히 복잡하고 혼란스러워 간략히만 살펴보니.. 배경 이미지 관련 더 세밀한 조정이 필요해지면; MDN)의 Background-position 문서를 참조하시기 바랍니다 ㅡㅡ;

                                                
                                                    /* 올바른 사용 */
                                                    background-position: left top; /* 좌상단 모서리 ← 기본값(0 0)이다! */
                                                    background-position: top left; /* 좌상단 모서리 ← 서로 다른 축인 경우; 순서는 상관없다! */                                 
                                                    background-position: left 50%; /* 좌단 가운데 */
                                                    background-position: center left; /* 좌단 가운데 ← left(및 left center)와 같다! */
                                                    background-position: right; /* 우단 가운데 ← 키워드 하나만 쓰면; 생략된 값에는 50%(center)가 들어간다! */
                                                    background-position: center; /* 박스 정중앙 ← center 하나는 박스 정중앙이 된다! */
            
                                                    background-position: bottom 70% right; /* 하단으로부터 70% 위 & 우단 */
                                                    background-position: right bottom 70%; /* 우단 & 하단으로부터 70% 위 */
            
                                                    background-position: bottom 70% right 30%; /* 하단으로부터 70% 위 & 우단으로부터 30% 앞 */
                                                    background-position: top 10px right 20px; /* 상단에서 10px 아래 & 우단으로부터 20px 앞 */                                   
            
                                                    /* 잘못된 사용 */
                                                    background-position: 50% left; /* 무슨 50%인지? ← 방향 키워드가 앞에 와야 한다! */
                                                    background-position: left right; /* 동일한 y축이다! */
                                                
                                            
배경 이미지 부착: background-attachment
background-attachment: scroll/fixed/local;(기본값: scroll) 속성을 사용하면 배경 레이어가 화면에 표시된 후 배경 이미지(백그라운드 레이어의 일부 이미지)의 고정 위치 동작을 수정할 수 있는데, fixed 값은 배경을 뷰포트에 대해 고정한다 곧, 해당 요소에 스크롤이 존재해도, 또 바깥 컨테이너 요소가 스크롤되어도 배경은 함께 스크롤되지 않으면서, 항시 자신의 원래 자리를 고수한다!

배경 이미지 부착 예)

배경 영역 설정: background-origin, background-clip
기본적으로 배경 이미지는 이미지의 (실제)너비와 높이 및 자연스러운 가로/세로 비율을 유지하면서, 이미지의 좌상단으로부터 시작하여 박스를 다 덮을 때까지 채워지는데, background-origin: border-box/padding-box/content-box; 속성은 해당 박스와 연결된 배경 영역을 설정해준다. 이는 또한, background-clip: border-box/padding-box/content-box; 속성과도 연관되어 있다:

배경 영역 설정 예)


background-clip 속성에는 컨텐츠 박스 내의 텍스트를 넘치지 않도록 배경을 자르는 text 값도 있는데, 이 효과가 적용되기 위해서는 대상 텍스트가 부분적으로 또는 완전히 투명해야 한다:

🐱 🐶

                                    
                                        
                                    
                                
                                    
                                        .text_box_ex {
                                            background-image: url("_images/남산부석-large.jpg");
                                            background-clip: text;
                                            color: transparent; /* 텍스트는 부분적으로 또는 완전히 투명해야한다! */
                                        }
                                    
                                
백그라운드 사이징: background-size
기본적으로 배경 이미지는 이미지의 (실제)너비와 높이 및 자연스러운 가로/세로 비율을 유지하면서, 이미지의 좌상단으로부터 시작하여 박스를 다 덮을 때까지 채워진다. background-size 속성값에는 배경 이미지의 실제 크기를 변경할 수 있는 가로 세로 크기값(단위는 px이나 %)을 사용할 수 있는데, 기본값인 auto는 이미지의 자연스러운 가로/세로 비율을 유지하면서 필요에 따라 크기가 조정된다:

백그라운드 사이징 예)


background: 값[, 값, ..]; 형식으로 배경 스타일을 일괄 설정해줄 수도 있는데(생략된 부분은 기본값으로 간주된다!), 지켜야하는 순서와 규칙도 좀 있고, 코드 읽기에도 많이 혼란스러우니 각각의 속성별로 개별적으로 설정해주는 것을 권합니다..

그라디언트 배경

그라디언트는 배경색의 점진적인 변화를 표시하는데, 자체적인 크기는 없다(그저 적용하는 요소의 크기와 같을 뿐이다!). 그라디언트는 이미지이며 이미지를 사용할 수 있는 모든 곳에서 사용할 수 있지만, 일반 이미지와는 달리 Css로 만들어지며 색상, 숫자, 각도 등으로 구성된다 그라디언트는 크기가 없는 배경 이미지이므로 background 속성으로 작성한다!

선형 그라디언트
linear-gradient(색상1, 색상2[, ..]); 함수는 2개 이상의 색상으로 된 이미지를 점진적으로 표시하는데, 가장 간단하게는 2개 이상의 색상만 인수로 주면 자동으로 (위에서 아래로 내려가면서)균등하게 분할하면서 혼합된다. 색상명 뒤에 숫자% 값을 추가하여 색상 중단점을 설정해줄 수도 있고, 색상명 앞에 to top/left/right/bottom 또는 숫자deg 값을 넣어 진행 방향을 지정해줄 수도 있다:
                                    
                                        
                                    
                                

맨 끝 그라디언트는 red 색상으로 시작하여 45도 각도로 진행되는데, 30% 지점(= 색상 중단점)에서 red 색상이 중지되고 인접한 yellow 색상과 혼합된다


원하는 만큼 색상과 색상 중단점을 추가할 수 있으며, 각각의 그라디언트를 ,로 구분하여 겹쳐줄 수도 있다: background: linear-gradient(45deg, darkred 20%, crimson, darkorange 60%, gold, bisque);

방사형(원 및 타원) 그라디언트
radial-gradient(); 함수는 각도를 지정하는 대신 원하는 경우 위치와 끝 모양을 지정한다. 색상만 주면 center 로 자동 선택되고 상자의 크기에 의해 원 또는 타원 모습이 결정된다:
                                    
                                        
                                    
                                

방사형 그라디언트에서도 (선형 그라디언트에서의 진행방향 키워드처럼)키워드를 쓸 수 있다: 기본값은 farthest-corner 는 상자의 중심에서 가장 먼 모서리를 정확하게 만나게 되며, closest-corner 는 이와 정 반대로 그라데이션 중심에서 가장 가까운 모서리를 만나게 된다. 한편, closest-side는 그라데이션의 중심에서 가장 가까운 측면과 만나게 된다

원추형 그라디언트
conic-gradient(); 함수는 기본적으로 박스 정 중앙을 중심점으로 하여 12시 방향에서 시작하여 360도 원형으로 진행된다. 키워드 및 숫자를 써서 중심점 위치를 변경해줄 수도 있다:
                                    
                                        
                                    
                                
                                    
                                        .conic-el_3 {
                                            background: conic-gradient(gold 20deg, lightcoral 20deg 190deg, mediumturquoise 190deg 220deg, plum 220deg 320deg, steelblue 320deg);
                                            border: 5px solid grey; border-radius: 50%; /* 5px 굵기의 테두리를 두른 원형 박스 */
                                        }
                                    
                                
그라디언트의 반복
위 각각의 그라디언트들을 반복하는 repeating-linear/radial/conic-gradient(); 함수도 있다:
                                    
                                        .linear-gradient_ex { background: linear-gradient(to right, red, orange, yellow, green, blue, indigo, violet); }
                                        .linear-repeat_ex { background: repeating-linear-gradient(to top left, lightpink, lightpink 5px, white 5px, white 10px); }
                                    
                                
                                    
                                        .radial-gradient_ex { background: radial-gradient(red, yellow, rgb(30, 144, 255)); }
                                        .radial-repeat_ex { background: repeating-radial-gradient(powderblue, powderblue 8px, white 8px, white 16px); }
                                    
                                

그라디언트를 직접 만드는 것은 재미도 없고, 수고스럽게 힘들이면서 많은 시간을 할애해야 하는 고된 작업이니,, 그라디언트를 자동으로 만들어주는 등의 그라디언트 자동생성기를 이용하는 것도 고려해보십시오 - 물론, 여유가 있다면; 폼나게 한번 만들어보시고요 ^^

대체요소 객체

Css에서 란 자신의 표시 결과가 Css의 범위를 벗어나는, Css 서식모델과는 분리된 외부 객체 인 요소로서 <img>나 <video> 요소가 대표적이다. Css는 대체요소 객체 Replaced Element 의 배치 위치 및 크기를 조정하여 영향을 줄 수 있지만 내용물 자체를 변경할 수는 없다!

대체요소 배치
object-position: 값1 값2; 속성은 <img>나 <video> 등 대체요소 객체의 배경 박스 내 컨텐츠 배치 위치(기본값: 50% 50% - 정중앙)을 지정하는데 (앞쪽 값은 좌측 면이 기준이 되고, 뒤쪽 값은 상단 면이 기준이 된다!), 대체요소 객체가 덮지 않은 부분은 요소의 배경이 드러나게 된다:
기본값인 50% 50%
                                            
                                                
                                            
                                        
                                            
                                                .object-position_image { /* 대체요소 객체의 배경 박스 */
                                                    width: 200px; height: 200px; background-color: silver;
                                                    object-fit: none;
                                                }
                                            
                                        

여기서는 object-position 값을 따로 주지 않았으므로, 기본값인 50% 50%가 된다!

단위로는 %, 키워드(top, right, bottom, left) 등을 쓸 수 있다. 예컨대, 기본값인 50% 50% 는 부모박스의 정중앙에 배치되고, 키워드 right top 으로 주면; 우상단 모서리로부터 맞추어지며, left bottom 으로 주면; 좌하단 모서리로부터 맞추어진다. px 단위 또한 사용할 수 있고, 단위를 혼합할 수도 있다:
object-position: right top object-position: left bottom object-position: 100% 30px

배경 박스보다 더 큰 값을 주어 지구 바깥으로 보내버릴 수도 있다:

object-position: 300px 300px
                                            
                                                
                                            
                                        
객체 맞춤
Object-fit: 키워드; 속성은 대체요소 객체가 부모 박스에 맞춰 채워지도록 다양한 방식으로 그 크기를 조정하는데 사용된다. none 값은 대체 콘텐츠의 크기를 조절하지 않으며, 기본값인 fill 에서는 컨텐츠가 부모 컨테이너를 꽉 채우는데, 필요한 경우 박스에 맞게 늘어나거나 줄어들게 된다:
object-fit: fill; (기본값) 매화
object-fit: none; 매화
contain 값을 주면; 대체되는 컨텐츠는 부모 컨테이너에 맞추어 종횡비를 유지하면서 크기가 조정된다. cover 값을 주면; 대체되는 컨텐츠는 부모 컨테이너에 맞추어 종횡비를 유지하면서 크기가 조정되는데, 원본 개체의 나머지 부분은 잘려나갈 수 있다:
object-fit: contain; 매화
object-fit: cover; 매화

Css 필터 효과

Css 속성은 이미지나 배경, 테두리 등에 다양한 효과 함수를 사용하여 블러나 색상 변형 등의 그래픽 효과를 적용한다. 한편, Backdrop Filter도 동일한 필터 함수들을 사용하는데, filter 속성이 요소 전체에 필터를 적용하는 반면, backdrop-filter 속성은 백그라운드에만 필터를 적용한다는 점에서 차이가 있다!

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

Css 필터링 예)


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

                                    
                                        
                                    
                                
백드롭 필터
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: 300px;
                                                        }
                                                    
                                                        .backdrop_filter {
                                                            padding: 1em 3em;
                                                            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;
                                                        }
                                                    
                                                

Drop Shadow

Css 는 Css의 box-shadow 속성과 다소간 유사하며, 속성값 설정 또한 비슷하다. 하지만, box-shadow 속성이 요소 전체 박스 뒤에 사각형 그림자를 그리는 반면, drop-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> 부분은 부트스트랩의 아이콘을 불러온 것입니다 부트스트랩 아이콘에 관해서는, 부트스트랩 강좌의 Svg 아이콘 부분을 참조하십시오..

Css 혼합 모드

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

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

* cf)

매화
남산부석
                                            
                                                .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 속성
isolation 속성은 z-index의 쌓임맥락과 유사하게 블렌딩 모드의 새로운 쌓임맥락을 만드는데, mix-blend-mode와 함께 사용할 때 특히 효율적이다 background-blend-mode에서는 (백그라운드 속성은 이미 격리되어 있으므로, 당연히)의미가 없다!
* 시작시, 부모요소의 배경색과 혼합되어 있음!
                                                    
                                                        
                                                    
                                                
                                                    
                                                        .isolate_demo {
                                                            background: rgb(198, 200, 181);
                                                            max-width: 600px; border: 5px solid gray; border-radius: 0.5rem; overflow: hidden;
                                                        } .isolate_demo img { mix-blend-mode: multiply; }
                                                    
                                                
                                                    
                                                        const iso_toggle= document.querySelector('#toggle-element3')
                                                        const iso_isolate= document.querySelector('.isolate_img')
                                                    
                                                        iso_toggle.addEventListener('change', ({target}) => {
                                                            iso_isolate.style.isolation= target.checked ? 'isolate' : 'auto';
                                                        });
                                                    
                                                
                                                    
                                                        
                                                    
                                                
                                                    
                                                        .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; }
                                                    
                                                
                                                    
                                                        
                                                    
                                                
                                                    
                                                        .isolate_ex2 {
                                                            isolation: isolate; /* 이 쌓임맥락 격리가 없으면 배경색까지 함께 혼합된다! */
                                                        } .isolate_ex2 circle { mix-blend-mode: screen; }
                                                    
                                                

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 등의 의사클래스가 사용되며, JavaScript를 쓸 수도 있다:
                                    
                                        .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));
                                        }
                                    
                                
                                                    
                                                        
                                                    
                                                
                                                    
                                                        .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);
                                                        }
                                                    
                                                

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

Css 트랜스폼

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

트랜스폼: transform
Css transform 속성은 Css 시각적 서식모델의 좌표 공간을 변경하는데, 이는 새로운 쌓임 맥락을 생성한다! - 이 경우, position 값이 fixed이거나 absolute인 요소의 컨테이닝 블록으로서 작동하게 된다. 추가적으로, transform-origin 속성으로 원점의 위치를 지정해줄 수도 있는데, 생략 시는 해당 요소의 중심이 된다:
Transform
Transform
Transform
                                    
                                        
                                    
                                

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

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

rotate() 예)

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

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

scaleX/Y() 예)


Css의 zoom 속성은 해당 요소를 확대/축소하는데, 기본값인 1100% 이상은 확대되고, 이하는 축소된다: 남산 로고

                                                
                                                    img.opacity_zoom { opacity: 0.9; }
                                                    img.opacity_zoom:hover { opacity: 0.5; zoom: 1.2; }
                                                
                                            

zoom 속성은 대상 요소의 크기를 조정하기에 페이지 레이아웃에 영향을 미칠 수 있다! 반면, transform: scale();을 사용하여 크기가 조정된 요소는 레이아웃이 재계산되거나 주변 다른 요소를 이동시키지 않는다 컨텐츠가 부모요소보다 커지게 되면; 오버플로된다!

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

🐱
🐶
                                                
                                                    .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(10deg);

🐶
                                                
                                                    .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; }
                                                    }
                                                
                                            
➥ 요소 기울이기

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

                                    
                                        
                                    
                                
                                    
                                        .rotate-15 { transform: rotate(15deg); }
                                        .rotate-n-15 { transform: rotate(-15deg); }
                                        /* 필요하다면; 같은 방식으로 더 추가해서 사용하면 됩니다 */
                                    
                                

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

Css @keyframes

일반적으로 애니메이션의 키프레임은 타임라인의 타임 스텝에 애니메이션의 상태를 할당하는 데 사용하는 메커니즘으로서, 시작과 종료 및 중간 지점들로 이루어진다. Css Animation에서의 @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 타임라인의 길이(애니메이션이 한 사이클을 완료하는 데 걸리는 지속시간)를 초(s)나 밀리초(ms) 값으로 정의하며, animation-delay: 대기시간;은 애니메이션이 시작되기 전 대기시간을 지정한다. 자연스러운 모션을 재현하기 위해 각 지점에서 애니메이션의 속도를 계산하는 animation-timing-function 함수를 사용할 수도 있는데, 그 값으로는 ease(기본값), linear, ease-in, ease-out, ease-in-out 키워드를 사용할 수 있다 계산된 값은 곡선형이므로 animation-duration 중에 그 값에 따르는 다양한 속도로 실행된다!
                                                    
                                                        
                                                    
                                                
                                                    
                                                        .demo_step {
                                                            animation: move;
                                                            animation-delay: 3s;
                                                            animation-duration: 10s;
                                                            animation-iteration-count: infinite;
                                                        } @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-iteration-count: 횟수; 속성은 애니메이션 중에 @keyframes 타임라인의 반복횟수 (기본값: 1)를 지정하는데, 애니메이션 루프를 만들려면; infinite 값을 주면 된다. 한편, 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';
                                                        });
                                                    
                                                

선을 따라 이동하는 대신 간격을 두고 이동하여 애니메이션을 더 세부적으로 제어하고 싶다면; 위 코드에서와 같이 animationTimingFunction 속성값에 steps(단계수 [start/end]); 함수를 써서 타임라인을 동일한 길이의 정의된 간격으로 나누어줄 수 있다!


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

베이직 쉐이프

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

쉐이프 도형 작성
쉐이프 도형을 만들 때 기본 참조상자는 basic-shape 값을 사용하는 속성에 의해 정의되는데, 쉐이프의 좌표계는 기본적으로 요소 박스의 좌상단 모서리가 원점이 되며, x축은 오른쪽으로, y축은 아래쪽으로 진행된다:
192x192 크기의 정사각 이미지 192x192 크기의 정사각 이미지
                                    
                                        
                                    
                                
                                    
                                        .shape_box { /* 기준이 되는 참조 박스 */
                                            width: 400px; margin: 0 auto;
                                        }
                                        
                                        .shape_box img.image1 { clip-path: inset(0 round 10%); }
                                        .shape_box img.image2 { clip-path: circle(); }
                                    
                                

clip-path 속성은 요소 자신의 클리핑 범위를 지정하는데, 클리핑 범위 안의 부분은 보여지고, 바깥은 숨겨진다 쉐이프 함수의 인수값 중 %로 표시되는 모든 길이는 참조상자의 크기에 의해(그에 대비한 비율로) 결정된다!

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

문단 옆에 원을 그려주고, Css 플로팅으로 좌우로 배치해봤는데.. 이 원은 Css 박스모델의 사각형 모양 그대로 문단 옆 사각 박스 영역만큼을 차지하면서 자리잡고 있군요 ㅡㅡ;

이 문단이 원을 따라서 둥글게 자리잡도록 할 수 있는 방법은 없을까요?

                                    
                                        
                                    
                                
                                    
                                        .s_circle { 
                                            width: 100px; height: 100px; border-radius: 50%; background-color: #77b597;
                                            float: left;
                                        }
                                    
                                
1. 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 값을 함께 넣어주어야 한다!

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

* Css로 그래픽을 다루는건 (메뉴를 선택하여 효과를 적용하는 그래픽 프로그램들과는 달리, 관련 속성들의 모양을 수치로 계산하여 적용해야 하기에)좀, 많이,, 더 어렵습니다 ㅡㅡ;

                                                    
                                                        
                                                    
                                                
                                                    
                                                        .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;
                                                        }
                                                    
                                                

Css Shape는 Css 박스모델 개념을 상속하지만, 이는 Shape 요소 자신의 외부에 적용되는 것이고, 이를 통해 주변 요소의 위치를 재설정해줄 수 있다 예컨대, Shape 요소에 shape-outside: circle() padding-box; 값을 주면; 주변 요소는 이 Shape 원의 마진(기본값인 margin-box) 및 테두리 영역(border-box) 을 넘어 곧바로 패딩 영역에 달라붙게 된다!

쉐이프 함수
inset(값 값 값 값 [round 값]); 함수는 박스의 각 측면에서 지정된 인셋 거리에 사각형을 정의한다. 앞쪽 인수는 상자 안쪽으로 상/우/하/좌로부터의 인셋 거리이며(인수의 개수는 3, 2, 1의 단축값으로 줄 수도 있다), 추가 옵션인 round 값(값은 1, 2, 3, 4개까지 줄 수 있다) 인수는 박스 코너(좌상, 우상, 우하, 좌하 순서임) 둥근 모서리를 설정한다 단위는 px% 모두 가능하다
                                    
                                        
                                    
                                
                                    
                                        .shape_inset {
                                            width: 120px; height: 80px; margin: 10px 10px 10px 40px; background-color: coral; float: left;
                                            clip-path: inset(30px 50px 15px 0 round 25px);
                                            shape-outside: inset(40px 40px 10px 0 round 25px);
                                        }
                                    
                                
남산부석

rect(); 함수는 컨테이너 박스의 좌상단 원점으로부터 지정된 거리에 사각형을 정의한다. circle(); 함수는 반지름과 위치를 이용하여 원 도형을 정의한다(circle(50px at 30% 70%);). ellipse(); 함수는 (타원이므로)두 개의 반지름을 지정해야 한다는 점을 제외하고는 circle(); 함수와 매우 유사한 방식으로 작동한다(ellipse(100px 200px at 10% 20%);):

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

                                                    
                                                        
                                                    
                                                
                                                    
                                                        .shape_circle {
                                                            max-width: 800px; margin: 0 auto; display: flow-root; /* 플로팅 해제용 */
                                                        } .shape_circle img {
                                                            float: left; margin-right: 1.5em;
                                                            clip-path: circle(); /* 쉐이프 원 */
                                                            shape-outside: circle(); /* 원 옆 문단 */
                                                        }
                                                    
                                                
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의 리버밴딩 효과 까지 방지한다:

참고로, 스크롤하여 새로고침 작업을 사용 중지하는 것은 전체 뷰포트 정의 요소(대개, <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 속성을 사용하여 조정해줄 수도 있다!


자식 요소 중 하나의 컨텐츠가 부모 컨테이너를 넘칠 경우라면; 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;
                                            }
                                        
                                    

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

wave