미리보기
해당 포스트를 따라오시면, 아래와 같은 애니메이션을 구현하실 수 있게 됩니다.
HTML
HTML 구조는 별게 없습니다. label 의 경우 인접 형제 선택자(+) 를 사용하기 위해 input 아래에 label 을 위치시켜 줍니다. 또한 input 의 경우 속성으로 required 를 지정해 줍니다. 유효성 검사를 통과하는 경우 input:valid { 속성들 } 로 지정한 속성들이 유지되도록 해주기 위해서 꼭 필요한 속성입니다.
<form action="#">
<div class="input_container">
<input id="username" type="text" required>
<label for="username">아이디</label>
</div>
<div class="input_container">
<input id="pw" type="password" required>
<label for="pw">비밀번호</label>
</div>
</form>
CSS
CSS 초기화
해당 부분은 불필요한 기본 CSS 속성을 제거하는 부분입니다. input 의 경우에는 기본 border 의 색상을 gray 로 설정하기 위해 border: 1px solid gray 로 지정 해줍니다. outline을 none 으로 지정하면 input 을 마우스 포커스 시 강조되는 외곽선이 사라지게 되므로, 지정해 줍니다.
box-sizing 의 경우 border-box 로 지정하게 되면, 콘텐츠 박스의 넓이를 구할 때 margin 과 padding 에 지정한 픽셀 크기을 포함시키게 됩니다. 즉, width 를 100px 로 지정할 때, 해당 요소가 100px 바깥을 벗어나지 않고 콘텐츠 박스와 여백의 크기를 합산 시 100px 에 맞춰서 계산됩니다.
* {
margin:0;
padding:0;
box-sizing:border-box;
}
input {
border:1px solid gray;
}
input:focus {
outline:none;
}
body | form 중앙정렬 및 배경색 지정
body 태그가 차지 하는 영역을 뷰포트 전체로 지정하고, form 요소를 화면의 중앙에 정렬하기 위해 display:flex, justify-content :center, align-items:center 를 각각 입력해 줍니다. 그리고 배경색이 약간 밝은 검정 느낌이 되도록 background: #333 을 지정해 줬습니다.
body {
width:100%;
height:100vh;
background:#333;
display:flex;
justify-content:center;
align-items:center;
}
form | 컨테이너 셋팅
form 태그는 input 컨테이너 전체를 감싸고 있는 외부 경계 역할을 하는 요소입니다. 해당 요소를 통해 input_container 로 지정된 요소들이 중앙정렬이 되고, 세로로 배치(flex-direction:column) 되도록 설정해줍니다. 나머지 크기를 설정하는 부분은 원하는 사이즈를 찾아서 자유롭게 맞춰가시면 됩니다.
form {
display:flex;
justify-content:center;
align-items:center;
flex-direction:column;
border-radius:5px;
max-width:768px;
width:100%;
height:350px;
}
Input_container | input 을 감싸고 있는 외곽선
해당 요소는 input 태그를 감싸고 있는 div 태그로 .input_container 라는 class 속성을 부여받고 있습니다.
.input_container {
padding:3.5px;
margin:8px 0;
position:relative;
animation: rotation 2s linear infinite;
animation-play-state: paused;
}
아래 화살표가 가리키고 있는 부분에 해당하며, 물결이 흐르는 듯한 애니메이션을 적용하는 대상입니다.
여기서 주요 속성은 position:relative 로 지정한 부분입니다. 나중에 label 태그에 position:absolute 를 지정할 겁니다. 이 때 절대좌표의 좌측 상단의 끝(0,0) 이 해당 요소가 되도록 하려면 relative 로 지정해주어야 합니다.
향후 포커스가 될 때 애니메이션을 실행하기 위해 그 전 까지는 애니메이션이 실행되지 않도록 animation-play-state 속성을 paused 로 지정해주었습니다. 또한 애니메이션이 부드럽게 무한 반복이 되도록 2s linear infinite 를 animation 속성에 지정해주었습니다. rotation 부분은 사용자 작명입니다.
position:relative;
animation: rotation 2s linear infinite;
animation-play-state: paused;
input 요소와 label 요소
input
input 태그 자체는 꾸미는 부분이라 크게 설명할 것이 없으므로 넘어 갑니다.
input {
border-radius:3px;
color:white;
background:#333;
padding:15px;
width:280px;
}
label
주요 하게 살펴볼 것은 label[for="username"] 이라고 지정한 부분 입니다. 여기서 for 은 label 태그가 가지고 있는 속성 중 하나인 for 을 의미합니다. 즉. for 속성의 값으로 username이 지정한 label 태그를 선택하여 width:70px 를 지정해주고 있는 겁니다. 이렇게 지정한 이유는 아이디 라벨이 차지하는 넓이보다 비밀번호 라벨이 차지하는 넓이가 더 크므로, 트랜잭션 적용 시 아이디 텍스트 사이에 공백이 부자연스럽기 때문에 이를 방지하기 위해서 입니다. 나머지는 label 태그를 꾸며주고 위치를 설정하기 위한 부분 입니다.
label[for="username"]{
width:70px;
}
label {
background:#333;
text-align:start;
padding: 0 5px;
font-size:1.15em;
width:85px;
border-radius:3px;
transition:0.5s;
color:white;
position:absolute;
top:0.7em;
left:0.4em;
}
여기 까지 작업하면, 아래와 동일한 결과를 얻을 수 있습니다.
포커스 시 효과 적용
이 부분은 포커스 시 적용한 효과를 설정하는 부분입니다.
아래 속성은 input_container 에 conic-gradient 형식으로 배경을 지정하고, 정지되어 있던 애니메이션을 실행하는 것 입니다. 여기서 :has(input:focus) 는 input 태그에 focus 시 해당 input 태그를 감싸고 있는 상위 태그에 css 를 적용하겠다는 의미입니다. .input_container 를 지정하였으므로, input 에 포커스 하면 .input_container 에 속성이 적용 됩니다.
.input_container:has(input:focus) {
background: conic-gradient(red, gold, orange,red);
animation-play-state: running;
}
:is(input:focus, input:valid) 는 지정한 두 선택자 모두에게 동일한 속성을 지정 합니다. 여기서 input 를 포커스 하고, input 에 입력된 텍스트가 유효한 경우 label 태그에 속성을 지정하겠다는 의미가 됩니다. 아래 속성은 모든 label 태그에 애니메이션을 적용하고, 트랜잭션 적용 시 움직일 위치를 지정해주고 있습니다. 또한, username 의 경우 label 태그에 지정한 아이디 라는 텍스트가 차지하는 넓이에 맞게 width를 개별적으로 지정해줍니다.
:is(input:focus, input:valid) + label
{
animation: rotation 2s linear infinite;
background: conic-gradient(red, gold, orange,red);
font-size:0.85em;
width:65px;
left:0.5em;
top:-0.5em;
}
:is(input:focus, input:valid) + label[for="username"] {
width:52.5px;
}
아래 코드에서 animation 을 적용해주고 있습니다. 이는 .input_container 에 적용한 animation 과 동일합니다.
:is(input:focus, input:valid) + label
{
animation: rotation 2s linear infinite;
background: conic-gradient(red, gold, orange,red);
font-size:0.85em;
width:65px;
left:0.5em;
top:-0.5em;
}
키프레임 정의 및 애니메이션 실행
이제 애니메이션을 실제 동작 시켜 줍니다.
@keyframes rotation {
0% {
background-position-x:0;
}
100% {
background-position-x:250px;
}
}
지정한 background-position-x 에 대해 설명하자면 요소에 적용된 배경 혹은 배경이미지의 X 축 좌표를 나타냅니다. 여기서 0px 로 지정하면 아래와 같이 수평의 좌측으로 정렬된 것을 볼 수 있습니다.
여기서 250px 로 지정하면 초기에 0px 지점에 있던 배경의 요소가 우측으로 250px 이동한 것을 볼 수 있습니다.
애니메이션이 진행되는 키프레임 0% 에서 100% 까지 background-position-x 의 값 또한 0px ~ 250px 이 될 때 까지 1px 씩 증가하며 애니메이션이 진행됩니다. 물론 앞서 .input_container 에 지정한 2초 동안 250px 까지 움직이는 것이므로, 빠르게 진행이 되겠죠.
현재 예시에서 만들고 있는 input 의 width가 280px 정도 이므로, background 를 0px 지점에서 250px 까지의 약간의 여유를 두고 끝나는 거리이며, 그 끝 지점에서 infinite 로 인해 다시 처음 위치로 이동하고, 우리가 보기에는 자연스럽게 물결 흐름이 이어지는 것 처럼 보이게 됩니다.
.input_container {
padding:3.5px;
margin:8px 0;
position:relative;
animation: rotation 2s linear infinite;
animation-play-state: paused;
}
구현결과
고생하셨습니다. 약간 부자연스러운 부분이 있는데 해당 부분은 input 의 width 와 background-position-x 의 끝지점에 지정한 px 값이 차이가 나서 그렇습니다. 예시에서 width 가 280px 로 input 에 적용되어 있는데, 이를 적용해보시면 지금보다 자연스럽게 움직일 겁니다. 저는 아래 흐름이 마음에 들어서 이대로 사용하였습니다.
See the Pen Untitled by youngwan2 (@youngwan2) on CodePen.
다음 애니메이션 | 뉴스 티커
'UI 디자인 애니메이션 연구소' 카테고리의 다른 글
어디가 끝이지? 끝없이 흘러가는 마키 UI 애니메이션 (0) | 2024.06.28 |
---|---|
스크롤링 헤드라인 이라 불리는 뉴스티커 UI, 원리부터 구현 까지 (1) | 2024.06.27 |
HTML/CSS/JS 를 이용한 스트리밍효과 토글 UI 만들기 (0) | 2024.06.16 |
CSS, JS를 이용한 웅장한 N-S(자석) 애니메이션 제작 (0) | 2024.06.07 |
HTML,CSS 를 사용한 3D 카드 회전 애니메이션 만들기 (0) | 2024.06.01 |