I'm trying to implement a simple script to manage resizing the textarea to fit the content. It works perfectly when adding content but every time I press the backspace key the scrollheight value increases by 3px!
document.querySelectorAll('textarea').forEach( element => {
element.style.height = `${element.scrollHeight}px`
element.addEventListener('input', event => {
event.target.style.height = 'auto' // added this line
event.target.style.height = `${event.target.scrollHeight}px`
})
})
/* style.css */
main, header {
max-width: 600px;
margin: auto;
}
textarea {
font-family: 'Times New Roman', Times, serif;
border-style: hidden;
outline: none;
padding: 0.1em;
margin: none;
resize: none;
width: 80%;
}
textarea:focus {
border: 1px solid #DDD;
border-radius: 0.2em;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf8" />
<meta name="viewport" content="width=device-width", initial-scale="1.0" />
<title>Data Management</title>
<link href="style.css" rel="stylesheet" type="text/css">
<script type="module" src="./script.js" defer></script>
</head>
<body>
<header>
<h1>Data Management</h1>
</header>
<main>
<p><textarea id="article"></textarea></p>
</main>
</body>
</html>
Does anyone know the cause of this annoying behaviour?
CodePudding user response:
Explaining this requires understanding the box model. In this case, you are using scrollHeight
, which includes borders and padding of the element - this is why the height is incrementing on any change.
For this I'm assuming you just want the textarea to expand when it's about to overflow, i.e. a scrollbar appears. Rather than having it change on every input event, check only if the scrollHeight exceeds the clientHeight. Whenever that occurs, increase the rows
of the textarea in order to expand it.
document.querySelectorAll('textarea').forEach(element => {
element.addEventListener('input', event => {
while (event.target.scrollHeight > event.target.clientHeight) {
event.target.rows ;
}
});
})
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf8" />
<meta name="viewport" content="width=device-width" , initial-scale="1.0" />
<title>Data Management</title>
<link href="style.css" rel="stylesheet" type="text/css">
<script type="module" src="./script.js" defer></script>
</head>
<body>
<header>
<h1>Data Management</h1>
</header>
<main>
<p><textarea id="article"></textarea></p>
</main>
</body>
</html>
CodePudding user response:
Problem:
You addEventListener
to any input
Solution:
Filter by keycode
this.onkeyup = function(e) {
if (e.keyCode != 32) {
// Your code here
}
}
You can use this site to know the for any keyboard input keycode.info
You can find snipt
document.querySelectorAll('textarea').forEach(element => {
element.style.height = `${element.scrollHeight}px`
this.onkeyup = function(e) {
if (e.keyCode != 32) {
element.addEventListener('input', event => {
event.target.style.height = `${event.target.scrollHeight}px`
})
}
}
})
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf8" />
<meta name="viewport" content="width=device-width" , initial-scale="1.0" />
<title>Data Management</title>
<link href="style.css" rel="stylesheet" type="text/css">
<script type="module" src="./script.js" defer></script>
</head>
<body>
<header>
<h1>Data Management</h1>
</header>
<main>
<p>
<textarea id="article"></textarea>
</p>
</main>
</body>
</html>
CodePudding user response:
I finally figured out what the problem was (and how to fix it). The solution was to set the height of the textarea to auto before resizing it to fit the contents (see below). I would be curious to know why this works...
/* script.js */
console.log('script loaded')
document.querySelectorAll('textarea').forEach( element => {
element.style.height = `${element.scrollHeight}px`
element.addEventListener('input', event => {
event.target.style.height = 'auto' // added this line
event.target.style.height = `${event.target.scrollHeight}px`
})
})