Появление белой области при увеличении и смещении textarea
Я захотел повторить textarea как у chatgpt (при переходе на новую строку он увеличивается, но не вниз, а вверх) и когда я перехожу на новую строку в textarea он увеличивается и смещается вверх, а внизу страницы появляется белая область, которая увеличивается с каждой новой строкой в textarea (относится только к тем строкам, при которых textarea увеличивается и смещается).
Режим разработчика:
document.getElementById("promptarea").addEventListener("input", function() {
var maxLength = 10;
var lines = this.value.split("\n");
// Предыдущая высота textarea
var prevHeight = this.clientHeight;
// Обрабатываем каждую строку
for (var i = 0; i < lines.length; i++) {
// Если строка длиннее maxLength, обрезаем её и добавляем перенос строки
if (lines[i].length > maxLength) {
lines[i] = lines[i].substring(0, maxLength) + "\n";
}
}
// Обновляем значение textarea
this.value = lines.join("\n");
// Устанавливаем высоту textarea в зависимости от содержимого
this.style.height = "";
var newHeight = Math.min(this.scrollHeight, 200);
this.style.height = newHeight + "px";
// Вычисляем смещение
var offset = 0;
if (newHeight !== prevHeight) {
offset = newHeight - prevHeight;
}
// Применяем смещение
this.style.top = parseFloat(getComputedStyle(this).top) - offset + "px";
});
@import url('https://fonts.googleapis.com/css2?family=Grape+Nuts&display=swap');
*{
margin: 0px;
padding: 0px;
}
.material-symbols-outlined {
font-variation-settings:
'FILL' #682b2b,
'wght' 400,
'GRAD' 0,
'opsz' 24
}
body {
background-repeat: no-repeat;
background-size: cover;
background-attachment: scroll;
min-height: 100vh;
min-width: 100vw;
display: inline-block;
}
.header{
background-color: #adadad;
width: 80vw;
height: 10vh;
justify-content: flex-end;
position: relative;
left: 20vw;
display: flex;
}
.nav{
text-align: center;
width: 60%;
position: absolute;
margin-top: 3vh;
left: 30%;
top: 0.4vh;
display: block;
z-index: 1;
}
.main{
background-color: #626262;
width: 100vw;
height: 90vh;
}
.aside{
color: #fff;
background-color: #000;
width: 20vw;
height: 100vh;
position: absolute;
}
.section {
background-color: #414141;
width: 80vw;
height: 10vh;
position: relative;
bottom: -80vh;
left: 20vw;
}
nav a{
transition: .3s;
font-family: 'Grape Nuts', calibri;
display: inline-block;
text-decoration: none;
color: #000;
border-radius: 5px;
font-size: 3vh;
display: inline;
padding: 0 20px;
background-color: #5b5a5a;
}
nav a:hover{
transition: .3s;
color: #fff;
background-color: #000;
}
#button{
height: 3vh;
margin: 47vh auto;
display: block;
}
#menu {
display: inline-block;
font-size: 10vh;
line-height: 1;
z-index: 2;
width: 100px;
height: 100px;
}
#menu:hover{
color: #ff0000;
cursor: pointer;
}
.section textarea{
position: relative;
height: 4vh;
margin-top: 3vh;
width: 85%;
margin-left: 3%;
margin-right: 3%;
resize: none;
border-radius: 4px;
overflow: hidden;
font-size: 16pt;
overflow: auto;
}
#prompt{
transition: .3s;
border: none;
color: inherit;
background-color: transparent;
cursor: pointer;
position: absolute;
left: calc(85% + 3% - 28pt);
top: 35%;
color: #000000;
}
/* .section{
background: #741818;
} */
.section textarea:placeholder-shown ~ #prompt{
transition: .3s;
border: none;
color: inherit;
background-color: transparent;
cursor: default;
position: absolute;
left: calc(85% + 3% - 28pt);
top: 35%;
color: #cccccc;
}
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="../css/stylesheet.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@24,400,0,0" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<aside class="aside">
<div class="dialogs">
<button type="button" id="button">Текст</button>
</div>
</aside>
<header class="header">
<div class="material-symbols-outlined menu-icon" id="menu">
menu
</div>
</header>
<nav class="nav">
<a href="html.htm">Главная</a>
<a href="#">Диалоги</a>
<a href="#">О нас</a>
</nav>
<main class="main">
<section class="section">
<textarea id="promptarea" name="" cols="30" rows="10" placeholder="Ваше сообщение..."></textarea>
<button class="material-symbols-outlined" id="prompt"> prompt_suggestion </button>
</section>
</main>
<script src="../js/talkpage.js"></script>
</body>
</html>
Ответы (1 шт):
Как было указано - проблема в использовании position:relative;
. В этом случае место под новую высоту продолжает выделяться.
Для решения достаточно изменить position
на absolute
у textarea
.
document.getElementById("promptarea").addEventListener("input", function() {
var maxLength = 10;
var lines = this.value.split("\n");
// Предыдущая высота textarea
var prevHeight = this.clientHeight;
// Обрабатываем каждую строку
for (var i = 0; i < lines.length; i++) {
// Если строка длиннее maxLength, обрезаем её и добавляем перенос строки
if (lines[i].length > maxLength) {
lines[i] = lines[i].substring(0, maxLength) + "\n";
}
}
// Обновляем значение textarea
this.value = lines.join("\n");
// Устанавливаем высоту textarea в зависимости от содержимого
this.style.height = "";
var newHeight = Math.min(this.scrollHeight, 200);
this.style.height = newHeight + "px";
// Вычисляем смещение
var offset = 0;
if (newHeight !== prevHeight) {
offset = newHeight - prevHeight;
}
// Применяем смещение
this.style.top = parseFloat(getComputedStyle(this).top) - offset + "px";
});
@import url('https://fonts.googleapis.com/css2?family=Grape+Nuts&display=swap');
*{
margin: 0px;
padding: 0px;
}
.material-symbols-outlined {
font-variation-settings:
'FILL' #682b2b,
'wght' 400,
'GRAD' 0,
'opsz' 24
}
body {
background-repeat: no-repeat;
background-size: cover;
background-attachment: scroll;
min-height: 100vh;
min-width: 100vw;
display: inline-block;
}
.header{
background-color: #adadad;
width: 80vw;
height: 10vh;
justify-content: flex-end;
position: relative;
left: 20vw;
display: flex;
}
.nav{
text-align: center;
width: 60%;
position: absolute;
margin-top: 3vh;
left: 30%;
top: 0.4vh;
display: block;
z-index: 1;
}
.main{
background-color: #626262;
width: 100vw;
height: 90vh;
}
.aside{
color: #fff;
background-color: #000;
width: 20vw;
height: 100vh;
position: absolute;
}
.section {
background-color: #414141;
width: 80vw;
height: 10vh;
position: relative;
bottom: -80vh;
left: 20vw;
}
nav a{
transition: .3s;
font-family: 'Grape Nuts', calibri;
display: inline-block;
text-decoration: none;
color: #000;
border-radius: 5px;
font-size: 3vh;
display: inline;
padding: 0 20px;
background-color: #5b5a5a;
}
nav a:hover{
transition: .3s;
color: #fff;
background-color: #000;
}
#button{
height: 3vh;
margin: 47vh auto;
display: block;
}
#menu {
display: inline-block;
font-size: 10vh;
line-height: 1;
z-index: 2;
width: 100px;
height: 100px;
}
#menu:hover{
color: #ff0000;
cursor: pointer;
}
.section textarea{
position: absolute;
height: 4vh;
margin-top: 3vh;
width: 85%;
margin-left: 3%;
margin-right: 3%;
resize: none;
border-radius: 4px;
overflow: hidden;
font-size: 16pt;
overflow: auto;
}
#prompt{
transition: .3s;
border: none;
color: inherit;
background-color: transparent;
cursor: pointer;
position: absolute;
left: calc(85% + 3% - 28pt);
top: 35%;
color: #000000;
}
/* .section{
background: #741818;
} */
.section textarea:placeholder-shown ~ #prompt{
transition: .3s;
border: none;
color: inherit;
background-color: transparent;
cursor: default;
position: absolute;
left: calc(85% + 3% - 28pt);
top: 35%;
color: #cccccc;
}
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="../css/stylesheet.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@24,400,0,0" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<aside class="aside">
<div class="dialogs">
<button type="button" id="button">Текст</button>
</div>
</aside>
<header class="header">
<div class="material-symbols-outlined menu-icon" id="menu">
menu
</div>
</header>
<nav class="nav">
<a href="html.htm">Главная</a>
<a href="#">Диалоги</a>
<a href="#">О нас</a>
</nav>
<main class="main">
<section class="section">
<textarea id="promptarea" name="" cols="30" rows="10" placeholder="Ваше сообщение..."></textarea>
<button class="material-symbols-outlined" id="prompt"> prompt_suggestion </button>
</section>
</main>
<script src="../js/talkpage.js"></script>
</body>
</html>
Также можно немного упростить код, и не рассчитывать top
. Для этого достаточно привязать textarea
к нижнему краю, а не к верхнему, в этом случае позиция всегда одинаковая и достаточно пересчитать только высоту.
document.getElementById("promptarea").addEventListener("input", function() {
var maxLength = 10;
var lines = this.value.split("\n");
// Предыдущая высота textarea
var prevHeight = this.clientHeight;
// Обрабатываем каждую строку
for (var i = 0; i < lines.length; i++) {
// Если строка длиннее maxLength, обрезаем её и добавляем перенос строки
if (lines[i].length > maxLength) {
lines[i] = lines[i].substring(0, maxLength) + "\n";
}
}
// Обновляем значение textarea
this.value = lines.join("\n");
// Устанавливаем высоту textarea в зависимости от содержимого
this.style.height = "";
var newHeight = Math.min(this.scrollHeight, 200);
this.style.height = newHeight + "px";
});
@import url('https://fonts.googleapis.com/css2?family=Grape+Nuts&display=swap');
*{
margin: 0px;
padding: 0px;
}
.material-symbols-outlined {
font-variation-settings:
'FILL' #682b2b,
'wght' 400,
'GRAD' 0,
'opsz' 24
}
body {
background-repeat: no-repeat;
background-size: cover;
background-attachment: scroll;
min-height: 100vh;
min-width: 100vw;
display: inline-block;
}
.header{
background-color: #adadad;
width: 80vw;
height: 10vh;
justify-content: flex-end;
position: relative;
left: 20vw;
display: flex;
}
.nav{
text-align: center;
width: 60%;
position: absolute;
margin-top: 3vh;
left: 30%;
top: 0.4vh;
display: block;
z-index: 1;
}
.main{
background-color: #626262;
width: 100vw;
height: 90vh;
}
.aside{
color: #fff;
background-color: #000;
width: 20vw;
height: 100vh;
position: absolute;
}
.section {
background-color: #414141;
width: 80vw;
height: 10vh;
position: relative;
bottom: -80vh;
left: 20vw;
}
nav a{
transition: .3s;
font-family: 'Grape Nuts', calibri;
display: inline-block;
text-decoration: none;
color: #000;
border-radius: 5px;
font-size: 3vh;
display: inline;
padding: 0 20px;
background-color: #5b5a5a;
}
nav a:hover{
transition: .3s;
color: #fff;
background-color: #000;
}
#button{
height: 3vh;
margin: 47vh auto;
display: block;
}
#menu {
display: inline-block;
font-size: 10vh;
line-height: 1;
z-index: 2;
width: 100px;
height: 100px;
}
#menu:hover{
color: #ff0000;
cursor: pointer;
}
.section textarea{
position: absolute;
height: 4vh;
margin-bottom: 3vh;
bottom: 0;
width: 85%;
margin-left: 3%;
margin-right: 3%;
resize: none;
border-radius: 4px;
overflow: hidden;
font-size: 16pt;
overflow: auto;
}
#prompt{
transition: .3s;
border: none;
color: inherit;
background-color: transparent;
cursor: pointer;
position: absolute;
left: calc(85% + 3% - 28pt);
top: 35%;
color: #000000;
}
/* .section{
background: #741818;
} */
.section textarea:placeholder-shown ~ #prompt{
transition: .3s;
border: none;
color: inherit;
background-color: transparent;
cursor: default;
position: absolute;
left: calc(85% + 3% - 28pt);
top: 35%;
color: #cccccc;
}
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="../css/stylesheet.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@24,400,0,0" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<aside class="aside">
<div class="dialogs">
<button type="button" id="button">Текст</button>
</div>
</aside>
<header class="header">
<div class="material-symbols-outlined menu-icon" id="menu">
menu
</div>
</header>
<nav class="nav">
<a href="html.htm">Главная</a>
<a href="#">Диалоги</a>
<a href="#">О нас</a>
</nav>
<main class="main">
<section class="section">
<textarea id="promptarea" name="" cols="30" rows="10" placeholder="Ваше сообщение..."></textarea>
<button class="material-symbols-outlined" id="prompt"> prompt_suggestion </button>
</section>
</main>
<script src="../js/talkpage.js"></script>
</body>
</html>