오늘은~ input 창안에 버튼을 넣어 이쁘게 보이게 하려고합니다!
Vue를 이용해 제작하고 있습니다.
많은 헤딩끝에 원하는 디자인대로 만들어 낸 과정을 작성합니다!
급하신분들은 맨 밑 '최종_최종최최종 코드'를 확인해주세요~!

1차 시도
처음엔 input창안에 button을 넣어서 원하는 디자인을 만들려고 했습니다.
//첫 코드
<template>
<form @submit="submitSearchBox">
<input v-model="searchWord" type="text" placeholder="검색어를 입력해주세요." required >
<button type="submit"><searchIcon/></button>
</form>
</template>
input 안에 button을 넣으려면 한번 감싸줘야합니다. 저는 label을 사용해 감싸줬습니다.
<template>
<form @submit="submitSearchBox">
<label>
<input v-model="searchWord" type="text" placeholder="검색어를 입력해주세요." required >
<button type="submit"><searchIcon/></button>
</label>
</form>
</template>
label{
position:relative
}
button{
position:absolute
left:7px;
top: 4px;
}
이렇게 작성 해주고 input창 그림자도 넣어주고 사이즈도 맞춰서 각종 브라우저에 테스트를 해보았는데 이상하게 버튼이 가운데에 있지않았습니다.(두둥)

브라우저마다 버튼 위치가 조금씩 이상해서 이방법으론 안된다라는 생각이 들었습니다.
이방법의 최대의 단점 input창 안에 들어가는 글자가 많아지면 버튼 밑으로 숨겨지기 때문에 maxlength를 설정해주어야합니다.
여기서 어떻게든 해결하고 싶어서 헤딩을 많이 했지만 그 헤딩 과정을 다 적기엔..너무 불필요하니 그저.. 오랜시간 헤딩한것만 알아주세요.
모든 블로그들을 찾아보고 정리되어 있는대로 사용해봤지만..절레절레
그렇게 1차시도는 실패!

2차 시도
form 자체에 디자인을 입히고 input 창에 디자인을 지워서 해결하기!!!
마치 form 자체가 input창 인것처럼 속였습니다.(사기꾼 아닙니다.)

<template>
<form @submit="submitSearchBox">
<input v-model="searchWord" type="text" placeholder="검색어를 입력해주세요." required >
<button type="submit"><searchIcon/></button>
</form>
</template>
첫번째 코드로 돌아갔습니다.
그리고 input에 설정해준 css를 form으로 옮겨 주고 flex를 적용시켜 줬습니다.
form{
display: flex;
align-items: center;
width: 80%;
height: 2.5rem;
font-size: 1rem;
border: 0;
border-radius: 0.5rem;
outline: none;
padding-left: 0.625rem;
background-color: white;
box-shadow: 0 0 0.375rem 0.0625rem gainsboro;
margin: 1.25rem auto;
}
button{
height: 1.7rem;
width: 1.7rem;
margin: 0 0.625rem;
border: 0;
border-radius: 0.5rem;
outline: none;
background: black;
color: white;
text-align: -webkit-center;
text-align: -moz-center;
}
input[type='text']{
height: 2.25rem;
font-size: 1rem;
border: 0;
border-radius: 0.5rem;
outline: none;
flex: 1;
}
버튼 아래로 글씨가 숨겨지지도 않고,원하는대로 디자인이 잘 나왔습니다
보다 보니 focus 가 될 때와 안 될때 차이가 없다 보니까 차이가 있게 만들고 싶었습니다.
일반 js에서는 dom요소를 가져와서 classList .add, .remove로 class를 넣어주고 지워주면 됬는데 vue에서는 그렇게 하지 않아도 해결이 됩니다!
1. ref를 사용하는 방법
2. 다이나믹 class를 사용하는 방법
1. ref 사용
<template>
<form @submit="submitSearchBox" ref="form">
<input v-model="searchWord" type="text" placeholder="검색어를 입력해주세요." required @focusin="focusIn" @focusout="focusOut">
<button type="submit"><searchIcon/></button>
</form>
</template>
methods: {
submitSearchBox: function (event) {
event.preventDefault();
this.searchWord = ''
},
focusIn: function(){
this.refs.form.classList.add('formFocus')
},
focusOut: function(){
this.refs.form.classList.remove('formFocus')
},
}
.formFocus{
border: 0.0625rem solid;
height: 2.375rem;
}
html 태그에는 ref라고 사용하고 methods에서 사용할때는 refs라고 해줘야합니다!
이렇게해 input창에 focus가 되면 form에 테두리를 줘서 클릭된 걸 사용자가 확인 할 수 있습니다.
2. 다이나믹 class 사용하기
저는 이 방법을 사용했습니다. 간결하고 직관적이기 때문이죠!
<form @submit="submitSearchBox" :class="{formFocus: formFocusOn}">
<input v-model="searchWord" type="text" placeholder="검색어를 입력해주세요." required @focusin="formFocusOn = true" @focusout="formFocusOn = false">
<button type="submit"><searchIcon/></button>
</form>
data() {
return {
searchWord: '',
formFocusOn: false
}
},
데이터 안에 formFocusOn이라는 변수를 하나 만들어주고, input창에 focusin, focusout로 변수를 컨드롤을 해주고 변수가 ture면 class가 추가되고 그렇지않으면 class가 지워집니다.
간단하게 해결되죠?!
마치 form이 input 창 인것처럼 만들어 줬습니다!
검색 아이콘은 css.gg라는 라이브러리를 사용 했습니다. css를 이용하는 것이기때문에 성능에서 좋다는 글을 보았거든요!
*TMI
포커스될때 form의 height사이즈를 변경해주는데 그이유는 border가 1씩 위아래 추가가 되기때문에 그대로 설정해주면 화면이 움직이는것처럼 보이거든요! 그래서 사이즈를 2줄여줘서 선이 생기든 안생기든 사이즈를 똑같이 보이게 하기 위해 줄여줬습니다!
-> 수정
css 속성 box-sizing을 이용해서 border-box로 설정해주면 border값까지 계산 되기 때문에 height 변경해주지 않고 해결할수 있습니다!
'최종_최종최최종 코드'
<template>
<form @submit="submitSearchBox" :class="{formFocus: formFocusOn}">
<input v-model="searchWord" type="text" placeholder="검색어를 입력해주세요." required @focusin="formFocusOn = true" @focusout="formFocusOn = false">
<button type="submit"><searchIcon/></button>
</form>
</template>
<script>
import searchIcon from "@/components/icons/searchIcon";
export default {
name: 'Appbar',
data() {
return {
searchWord: '',
formFocusOn: false
}
},
components:{
searchIcon
},
methods: {
submitSearchBox: function (event) {
event.preventDefault();
this.searchWord = ''
}
}
}
</script>
<style scoped>
form{
display: flex;
align-items: center;
width: 80%;
height: 2.5rem;
font-size: 1rem;
border: 0;
border-radius: 0.5rem;
outline: none;
padding-left: 0.625rem;
background-color: white;
box-shadow: 0 0 0.375rem 0.0625rem gainsboro;
margin: 1.25rem auto;
}
button{
height: 1.7rem;
width: 1.7rem;
margin: 0 0.625rem;
border: 0;
border-radius: 0.5rem;
outline: none;
background: black;
color: white;
text-align: -webkit-center;
text-align: -moz-center;
}
input[type='text']{
height: 2.25rem;
font-size: 1rem;
border: 0;
border-radius: 0.5rem;
outline: none;
flex: 1;
}
input[type='text']:focus{
caret-color: red;
}
.formFocus{
border: 0.0625rem solid;
height: 2.375rem;
}
</style>
'CSS' 카테고리의 다른 글
[CSS]텍스트에 그라데이션, 이미지 적용하기 (0) | 2023.04.18 |
---|---|
[CSS] 박스 가운데 정렬 방법 (0) | 2023.03.15 |
[CSS] background 관련 정리 (0) | 2023.02.20 |
웹 접근성을 생각한 radio button style custom (0) | 2023.02.08 |
그라데이션 설정법 (0) | 2023.01.18 |