본문 바로가기

UI 디자인 애니메이션 연구소

HTML, CSS 로 불타는 입력창(Input) 만들기

반응형

미리보기

해당 포스트를 따라오시면, 아래와 같은 애니메이션을 구현하실 수 있게 됩니다.

 

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, 원리부터 구현 까지

이전 애니메이션 HTML, CSS 로 불타는 입력창(Input) 만들기미리보기해당 포스트를 따라오시면, 아래와 같은 애니메이션을 구현하실 수 있게 됩니다. HTMLHTML 구조는 별게 없습니다. label 의 경우 인

duklook.tistory.com

 

반응형