前置き
formで使うinput, textarea
中でも何かと使い勝手の悪いtextareaさん😕
HTMLのグローバル属性
contenteditableを使って
textareaをもっと見やすくしてみましょう!
textarea
contenteditable
contenteditableって?
簡単にいうと編集モードにしてくれます。
編集できる+文字数に応じて幅が変化します!
分かりやすくbuttonタグにつけましたが
グローバル属性のため、どのタグにつけてもOKです。
ただし
textareaにはcontenteditable属性が使えません!
そのためtextarea風の入力欄を作るには
divにつけて擬似的に作ります!
1 2 3 4 5 6 7 |
<template> <button contenteditable="true" > 編集できるよ </button> </template> |
使いやすさ比較
textarea
- 基本的に高さが固定されるので全体が見えない
リサイズボタンで拡大縮小できるけど - 横幅も動いて見にくい
- リサイズボタンがデザインできない
resize: none;で消すと拡大縮小できない - 色々使い勝手が悪い
div contenteditable="true"
- 横幅だけ固定してしまえば
- 縦幅が文字数に応じて伸縮し
とっても見やすい!!✨👀
コード比較
textarea
chromeだとフォントサイズが
小さく見えることがあります。
なのでtextareaの場合のみ
font-size: 100%; を追記します✍️
デフォルトのフォントサイズ16pxを指定すると
font-familyも変わる場合があるようです。
1 |
font-size: 100%; |
1 2 |
font-size: 16px; font-family: 'フォント名' |
このどちらかで調整しましょう!
) components
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
<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> |
) pages
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
<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> |
div contenteditable="true"
textareaをdiv contenteditable="true"に変更!
複数行になるためrole="textbox"も追加💡
cssはtextareaとほとんど変わりません。
ただし当然ですがinput, textareaの
placeholder属性は使えません😣💦
) components
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
<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> |
) pages
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
<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> |