【Nuxt.js】form実践編：contenteditableでイライラ解消！

# 前置き

formで使うinput, textarea
中でも何かと使い勝手の悪いtextareaさん😕
HTMLのグローバル属性
contenteditableを使って
textareaをもっと見やすくしてみましょう！


**textarea**
![textarea.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469755/65183365-2168-494e-7c87-502007e78570.gif)

**contenteditable**
![div.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469755/81989bfa-a764-dc84-7bad-2663c6ddb71a.gif)


# contenteditableって？

簡単にいうと編集モードにしてくれます。
分かりやすくbuttonタグにつけました。
編集できる＋文字数に応じて幅が変化してくれます！
![button.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469755/c7e63b1c-6a7b-7bab-3839-f4bea43f0fa9.gif)

```vue:index.vue
<template>
 <button
   contenteditable="true"
 >
   編集できるよ
 </button>
</template>
```

# 使いやすさ比較

**・textareaの場合**
**・div contenteditable="true"の場合**

textareaにcontenteditable="true"は
使えないため擬似的にtextareaを作成🌟

**◾️textarea**
・基本的に高さが固定されるので全体が見えない
　リサイズボタンで拡大縮小できるけど
・横幅も動いて見にくい
・リサイズボタンがデザインできない
　resize: none;で消してしまうと拡大縮小できない
・色々使い勝手が悪い
![textarea.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469755/d77a088c-2da1-254d-f82e-c9d3a07b6639.gif)

**◾️div contenteditable="true"**
・横幅だけ固定してしまえば
・縦幅が文字数に応じて伸縮し
　とっても見やすい！！✨👀
![div.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469755/f04bdaf5-2820-43f9-565f-3c734bc36240.gif)

# コード

**◾️div contenteditable="true"の場合**
textareaをdiv contenteditable="true"に変更！
今回は複数行になるため**role="textbox"**も追加💡

cssはtextareaとほとんど変わりません。
ただし当然ですがinput, textareaの
placeholder属性は使えません😣


```vue:Contenteditable.vue
<template>
 <label
  class="contenteditable"
 >
  <span class="label">
    {{ label }}
  </span>
  <div
    class="contenteditable"
    contenteditable="true"
    role="textbox"
    @input="$emit('input', $event.target.textContent)"
  />
 </label>
</template>

<script>
export default {
props: {
  label: {
    type: String,
    default: 'label',
  },
}
</script>

<style lang="scss" scoped>
.contenteditable {
  display: flex;
  align-items: flex-start;

  > .label {
    color: red;
    font-weight: bold;
    width: 64px;
    min-width: 64px;
    padding-top: 4px;
  }

  > .textarea {
    width: calc(100% - 64px);
    min-height: 70px;
    padding: 8px 12px;
    border: 2px solid red;
  }
}
</style>
```vue

```vue:index.vue
<template>
 <div class="page">
   <Contenteditable
     label="LABEL"
     @input="text = $event"
   />
 </div>
</template>

<script>
import Contenteditable from '~/components/Contenteditable.vue'

export default {
 components: {
   Contenteditable,
 },
 data () {
  return {
   text: "",
  }
 },
}
</script>
```

**◾️textareaの場合**

chromeだとフォントサイズが
小さく見えることがあります。
なのでtextareaの場合のみ
font-size: 100%; を追記します✍️


デフォルトのフォントサイズ16pxを指定すると
font-familyも変わる場合があるようです。

**font-size: 100%;**

または

**font-size: 16px;
font-family: 'フォント名'**


```vue:Textarea.vue
<template>
 <label
  class="textarea"
 >
  <span class="label">
    {{ label }}
  </span>
  <textarea
    :placeholder="placeholder"
    class="textarea"
    @input="$emit('input', $event.target.textContent)"
  />
 </label>
</template>

<script>
export default {
props: {
  label: {
    type: String,
    default: 'label',
  },
  placeholder: String,
}
</script>

<style lang="scss" scoped>
.textarea {
  display: flex;
  align-items: flex-start;

  > .label {
    color: red;
    font-weight: bold;
    width: 64px;
    min-width: 64px;
    padding-top: 4px;
  }

  > .textarea {
    font-size: 100%;
    width: calc(100% - 64px);
    min-height: 70px;
    padding: 8px 12px;
    border: 2px solid red;
  }
}
</style>
```


```vue:index.vue
<template>
 <div class="page">
   <Textarea
     label="LABEL"
     placeholder="ここに入力してください"
     @input="text = $event"
   />
 </div>
</template>

<script>
import Textarea from '~/components/Textarea.vue'

export default {
 components: {
   Textarea,
 },
 data () {
  return {
   text: "",
  }
 },
}
</script>
```



**記事が公開したときにわかる様に、
note・Twitterフォローをお願いします😀**
https://twitter.com/aLizlab