transition
변화의 전, 후 사이에 애니메이션을 추가해서 움직임을 부드럽게 만들어 줄 수 있습니다.
:hover에 적용하면 마우스를 내리는 순간 해제되므로 해당 요소 자체에 transition을 적용한다.
transition-property
all이라는 키워드로 변화가 일어나는 해당 요소의 모든 속성을 한꺼번에 지정하기도 가능
transition-duration
transition에 걸리는 시간을 지정
duration은 초(s), 혹은 밀리초(ms) 단위로 지정이 가능합니다.
transition-duration: 0.2s
transiton-duration: 2000
transition-timing-function
transition의 속도 패턴을 지정
변화가 일정한 속도로 일어날 것 인지, 아니면 빠르게 시작했다가 느리게 끝날 것 인지 같은 속도 패턴
transition-duration: ease-in-out(가장 많이 사용됨) | linear | ease | ease-in | ease-out
예시 참고: https://codepen.io/Joogumi/full/eYMgrKO
transition-delay
transition 요청을 받은 후 실제로 실행되기까지 기다려야 하는 시간의 양을 지정
transiton을 순차적으로 일어나게 만들기 위해 사용
transition-delay: 2s
transition 단축 속성으로 많이 사용
순서 중요!
예시)
/* 모든 속성을 변형하고싶은 경우 */
.box {
transition: all 3s ease-in-out 1s;
}
/* 길이와 배경색을 순차적으로 변형하고싶은 경우 --> 길이는 0.5초 지연 후 변경된다. */
.box {
transition: background-color 0.5s ease-in-out, width 0.5s ease-in-out 0.5s;
}
//(index.css)
.item3 {
transition: background-color 0.5s ease-in-out, width 0.5s ease-in-out 0.5s;
}
.item3:hover {
width: 300px;
background: #002398;
}
실습 - transform + transition
- 상품 리스트
- hover 효과 (배경 이미지 확대 / 블러, 텍스트 transform + transition 효과)
(card.html)<!DOCTYPE html> <html lang="ko"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>My Shop - card</title> <link rel="stylesheet" href="./card.css" /> </head> <body> <div class="itemWrap"> <div class="item"> <div class="imgBox"> <img src="./img/item1.jpeg" alt="탁상용 조명" /> </div> <div class="textBox"> <p class="textBox-name">탁상용 조명</p> <p class="textBox-price">260,000 원</p> </div> </div> <div class="item"> <div class="imgBox"> <img src="./img/item2.png" alt="머그컵" /> </div> <div class="textBox"> <p class="textBox-name">머그컵</p> <p class="textBox-price">32,000 원</p> </div> </div> <div class="item"> <div class="imgBox"> <img src="./img/item3.jpeg" alt="거실용 슬리퍼" /> </div> <div class="textBox"> <p class="textBox-name">거실용 슬리퍼</p> <p class="textBox-price">28,000 원</p> </div> </div> <div class="item"> <div class="imgBox"> <img src="./img/item1.jpeg" alt="탁상용 조명" /> </div> <div class="textBox"> <p class="textBox-name">탁상용 조명</p> <p class="textBox-price">260,000 원</p> </div> </div> <div class="item"> <div class="imgBox"> <img src="./img/item2.png" alt="머그컵" /> </div> <div class="textBox"> <p class="textBox-name">머그컵</p> <p class="textBox-price">32,000 원</p> </div> </div> <div class="item"> <div class="imgBox"> <img src="./img/item3.jpeg" alt="거실용 슬리퍼" /> </div> <div class="textBox"> <p class="textBox-name">거실용 슬리퍼</p> <p class="textBox-price">28,000 원</p> </div> </div> <div class="item"> <div class="imgBox"> <img src="./img/item1.jpeg" alt="탁상용 조명" /> </div> <div class="textBox"> <p class="textBox-name">탁상용 조명</p> <p class="textBox-price">260,000 원</p> </div> </div> <div class="item"> <div class="imgBox"> <img src="./img/item2.png" alt="머그컵" /> </div> <div class="textBox"> <p class="textBox-name">머그컵</p> <p class="textBox-price">32,000 원</p> </div> </div> <div class="item"> <div class="imgBox"> <img src="./img/item3.jpeg" alt="거실용 슬리퍼" /> </div> <div class="textBox"> <p class="textBox-name">거실용 슬리퍼</p> <p class="textBox-price">28,000 원</p> </div> </div> <div class="item"> <div class="imgBox"> <img src="./img/item1.jpeg" alt="탁상용 조명" /> </div> <div class="textBox"> <p class="textBox-name">탁상용 조명</p> <p class="textBox-price">260,000 원</p> </div> </div> <div class="item"> <div class="imgBox"> <img src="./img/item2.png" alt="머그컵" /> </div> <div class="textBox"> <p class="textBox-name">머그컵</p> <p class="textBox-price">32,000 원</p> </div> </div> <div class="item"> <div class="imgBox"> <img src="./img/item3.jpeg" alt="거실용 슬리퍼" /> </div> <div class="textBox"> <p class="textBox-name">거실용 슬리퍼</p> <p class="textBox-price">28,000 원</p> </div> </div> </div> </body> </html>
(card.css)
* { box-sizing: border-box; } html, body { margin: 0; padding: 0; } .itemWrap { display: flex; flex-direction: row; justify-content: space-between; align-items: flex-start; flex-wrap: wrap; } .item { width: calc(25% - 7px); aspect-ratio: 6 / 5; position: relative; overflow: hidden; border-radius: 10px; margin-bottom: 15px; } .imgBox { width: 100%; height: 100%; } .imgBox img { width: 100%; height: 100%; object-fit: cover; } .textBox { width: 100%; height: 100%; position: absolute; top: 0; left: 0; display: flex; flex-direction: column; justify-content: flex-end; align-items: flex-start; padding: 20px; z-index: 3; } .textBox p { color: white; margin: 5px 0 0; } .textBox-name { font-size: 22px; font-weight: 500; opacity: 0; transform: translateY(50px); } .textBox-price { font-size: 16px; font-weight: 400; opacity: 0; transform: translateY(50px); } .item:after { content: ""; display: block; width: 100%; height: 100%; background: rgba(0, 0, 0, 0.2); position: absolute; top: 0; left: 0; z-index: 2; opacity: 0; } .item:hover:after { opacity: 1; } .item:hover .imgBox img { transform: scale(1.1); filter: blur(3px); } .item:hover .textBox-name { opacity: 1; transform: translateY(0); } .item:hover .textBox-price { opacity: 1; transform: translateY(0); } .item:after, .item .imgBox img, .item .textBox-name { transition: all 0.4s ease-in-out; } .item .textBox-price { transition: all 0.4s ease-in-out 0.15s; }