Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

textarea如何实现高度自适应 #112

Open
Seasons123 opened this issue Dec 25, 2019 · 2 comments
Open

textarea如何实现高度自适应 #112

Seasons123 opened this issue Dec 25, 2019 · 2 comments

Comments

@Seasons123
Copy link
Owner

Seasons123 commented Dec 25, 2019

今天需要些一个回复评论的页面,设计师给的初始界面就是一个只有一行的框。然后当时就想这个交互该怎么实现比较好,然后想起了新浪微博的做法:点击评论,默认显示一行,当输入的文字超过一行或者输入Enter时,输入框的高度会随着改变,直到输入完毕。顿时觉得这个细节做得挺不错的,可以效仿下。下面分享2种实现textarea高度自适应的做法,一种是利用JS控制的(因为存在浏览器兼容问题,所以写起来比较麻烦);另一种是用div来模拟textarea来实现的,用CSS控制样式,不用JS;

@Seasons123
Copy link
Owner Author

1.方法一:利用JS控制

<!DOCTYPE html> 
<html xmlns="http://www.w3.org/1999/xhtml" > 
<head> 
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 
<title>文本框根据输入内容自适应高度</title> 
<style type="text/css"> 
h2{
		text-align: center;
		margin:50px auto;
	}
#textarea { 
	display: block;
	margin:0 auto;
	overflow: hidden; 
	width: 550px; 
	font-size: 14px;
	height: 18px; 
	line-height: 24px;
	padding:2px; 
}
textarea {
	outline: 0 none;
	border-color: rgba(82, 168, 236, 0.8);
	box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1), 0 0 8px rgba(82, 168, 236, 0.6);
}
</style> 
<script>
/**
 * 文本框根据输入内容自适应高度
 * @param                {HTMLElement}        输入框元素
 * @param                {Number}                设置光标与输入框保持的距离(默认0)
 * @param                {Number}                设置最大高度(可选)
 */
var autoTextarea = function (elem, extra, maxHeight) {
        extra = extra || 0;
        var isFirefox = !!document.getBoxObjectFor || 'mozInnerScreenX' in window,
        isOpera = !!window.opera && !!window.opera.toString().indexOf('Opera'),
                addEvent = function (type, callback) {
                        elem.addEventListener ?
                                elem.addEventListener(type, callback, false) :
                                elem.attachEvent('on' + type, callback);
                },
                getStyle = elem.currentStyle ? function (name) {
                        var val = elem.currentStyle[name];
                        
                        if (name === 'height' && val.search(/px/i) !== 1) {
                                var rect = elem.getBoundingClientRect();
                                return rect.bottom - rect.top -
                                        parseFloat(getStyle('paddingTop')) -
                                        parseFloat(getStyle('paddingBottom')) + 'px';        
                        };
                        
                        return val;
                } : function (name) {
                                return getComputedStyle(elem, null)[name];
                },
                minHeight = parseFloat(getStyle('height'));
        
        
        elem.style.resize = 'none';
        
        var change = function () {
                var scrollTop, height,
                        padding = 0,
                        style = elem.style;
                
                if (elem._length === elem.value.length) return;
                elem._length = elem.value.length;
                
                if (!isFirefox && !isOpera) {
                        padding = parseInt(getStyle('paddingTop')) + parseInt(getStyle('paddingBottom'));
                };
                scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
                
                elem.style.height = minHeight + 'px';
                if (elem.scrollHeight > minHeight) {
                        if (maxHeight && elem.scrollHeight > maxHeight) {
                                height = maxHeight - padding;
                                style.overflowY = 'auto';
                        } else {
                                height = elem.scrollHeight - padding;
                                style.overflowY = 'hidden';
                        };
                        style.height = height + extra + 'px';
                        scrollTop += parseInt(style.height) - elem.currHeight;
                        document.body.scrollTop = scrollTop;
                        document.documentElement.scrollTop = scrollTop;
                        elem.currHeight = parseInt(style.height);
                };
        };
        
        addEvent('propertychange', change);
        addEvent('input', change);
        addEvent('focus', change);
        change();
};
</script> 
</head> 
<body> 
	<h2>文本框根据输入内容自适应高度</h2>
	<textarea id="textarea" placeholder="回复内容"></textarea> 
	<script> 
		var text = document.getElementById("textarea");
		autoTextarea(text);// 调用
	</script> 
</body> 
</html>

@Seasons123
Copy link
Owner Author

Seasons123 commented Dec 25, 2019

2.方法二:div模拟textarea文本
附上张鑫旭大神的这篇文章: div模拟textarea文本域轻松实现高度自适应
因为textarea不支持自适应高度,就是定好高度或者是行数之后,超出部分就会显示滚动条,看起来不美观。而用DIV来模拟时,首先遇到的问题是:div怎么实现输入功能?可能我们还是第一次见到这个属性contenteditable,如一个普通的block元素上加个contenteditable="true"就实现编辑,出现光标了。
CSS代码:

.test_box {
    width: 400px; 
    min-height: 120px; 
    max-height: 300px;
    _height: 120px; 
    margin-left: auto; 
    margin-right: auto; 
    padding: 3px; 
    outline: 0; 
    border: 1px solid #a0b3d6; 
    font-size: 12px; 
    word-wrap: break-word;
    overflow-x: hidden;
    overflow-y: auto;
    -webkit-user-modify: read-write-plaintext-only;
}

HTML代码:
<div class="test_box" contenteditable="true"><br /></div>
JS代码:

if (typeof document.webkitHidden == "undefined") {
    // 非chrome浏览器阻止粘贴
    box.onpaste = function() {
        return false;
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant