Is there any way to check if specified html element is in viewport - no window but specified div? I found only one meaningful solution but I can't make it work for me.
According to this question Check if element is visible in div
I created a example here: http://jsfiddle.net/jm91n80u/
This is my html code:
<body style="overflow:hidden;">
<div id="outer" style="position:absolute;left:150px;top:20px;right:100px;bottom:30px;overflow:hidden;border:1px solid blue;">
<div id="inner" style="position:relative;height:300px;border:1px solid red;width:100px;overflow-y:auto;overflow-x:hidden;">
<div style="position:relative;width:100%;height:30px;border:1px solid grey;" class="test">1</div>
<div style="position:relative;width:100%;height:30px;border:1px solid grey;" class="test">2</div>
<div style="position:relative;width:100%;height:30px;border:1px solid grey;" class="test">3</div>
<div style="position:relative;width:100%;height:30px;border:1px solid grey;background:yellow;" class="test" id="id1">4</div>
<div style="position:relative;width:100%;height:30px;border:1px solid grey;" class="test">5</div>
<div style="position:relative;width:100%;height:30px;border:1px solid grey;" class="test">6</div>
<div style="position:relative;width:100%;height:30px;border:1px solid grey;" class="test">7</div>
<div style="position:relative;width:100%;height:30px;border:1px solid grey;" class="test">8</div>
<div style="position:relative;width:100%;height:30px;border:1px solid grey;" class="test">9</div>
<div style="position:relative;width:100%;height:30px;border:1px solid grey;" class="test">10</div>
<div style="position:relative;width:100%;height:30px;border:1px solid grey;" class="test">11</div>
<div style="position:relative;width:100%;height:30px;border:1px solid grey;" class="test">12</div>
<div style="position:relative;width:100%;height:30px;border:1px solid grey;" class="test">13</div>
<div style="position:relative;width:100%;height:30px;border:1px solid grey;" class="test">14</div>
</div>
</div>
<div id="result" style="position:absolute;bottom:0px;overflow:hidden;border:1px solid black;height:20px;width:100%;"></div>
</body>
This is a js function
$(document).ready(function () {
$.belowthefold = function (lookIn, elements, settings) {
var fold = $(lookIn).height() + $(lookIn).scrollTop();
return $(elements).filter(function () {
return fold <= $(this).offset().top - settings.threshold;
});
};
$.abovethetop = function (lookIn, elements, settings) {
var top = $(lookIn).scrollTop();
return $(elements).filter(function () {
return top >= $(this).offset().top + $(this).height() - settings.threshold;
});
};
$.rightofscreen = function (lookIn, elements, settings) {
var fold = $(lookIn).width() + $(lookIn).scrollLeft() + $(lookIn).offset().width;
return $(elements).filter(function () {
return fold <= $(this).offset().left - settings.threshold;
});
};
$.leftofscreen = function (lookIn, elements, settings) {
var left = $(lookIn).scrollLeft();
return $(elements).filter(function () {
return left >= $(this).offset().left + $(this).width() - settings.threshold;
});
};
$("#inner").scrollTop(100);
var b = $.belowthefold("#inner", ".test", { threshold: 0 }).toArray();
var t = $.abovethetop("#inner", ".test", { threshold: 0 }).toArray();
var r = $.rightofscreen("#inner", ".test", { threshold: 0 }).toArray();
var l = $.leftofscreen("#inner", ".test", { threshold: 0 }).toArray();
var el = $("#id1")[0];
var bS = "below the fold : ";
for (var i = 0; i < b.length; i++) {
bS += $(b[i]).html() + ",";
}
var tS = "above the top : ";
for (var i = 0; i < t.length; i++) {
tS += $(t[i]).html() + ",";
}
var rS = "right of screen : ";
for (var i = 0; i < r.length; i++) {
rS += $(r[i]).html() + ",";
}
var lS = "left of screen : ";
for (var i = 0; i < l.length; i++) {
lS += $(l[i]).html() + ",";
}
console.log(bS);
console.log(tS);
console.log(rS);
console.log(lS);
});
What I'm trying to do is get all '.test' elements which are currently invisible (or partial invisible in target solution, any switch will be appreciated) in inner container with information about their position. The result of this should be:
below the fold : 13, 14
above the top : 1,2,3,4
right of screen :
left of screen :
But in this particular case those functions doesn't work. I tried use several other solutions, but each one treats viewport as window.
Can you explain what am I doing wrong? Any help will be appreciated.
You should compare div's positions to: viewport size and windows bounds.
Roughly : if(div.top > (window.top + viewport.height )) {/*this is visible*/} else {/*this is not visible*/}
You could even make it more specific (how much area of div ?)
if((div.top **+ 50% of div.height**) > (window.top + viewport.height )) {/*this is visible*/}
This post gives some codes Check if element is between 30% and 60% of the viewport
$(document).ready(function() {
// Get viewport height, gridTop and gridBottom
var windowHeight = $(window).height(),
gridTop = windowHeight * .3,
gridBottom = windowHeight * .6;
$(window).on('scroll', function() {
// On each scroll check if `li` is in interested viewport
$('ul li').each(function() {
var thisTop = $(this).offset().top - $(window).scrollTop(); // Get the `top` of this `li`
// Check if this element is in the interested viewport
if (thisTop >= gridTop && (thisTop + $(this).height()) <= gridBottom) {
$(this).css('background', 'red');
} else {
$(this).css('background', 'gray');
}
});
});
});
Related
I am working on the below code. Why am I not able to detect which div is reaching at the top of page in both down or up scroll?
$(window).scroll(function() {
$(".container").each(function() {
var $that = $(this);
var po = $(this).offset().top;
if (po >= 0 && po <= 300) {
console.log($that.data('map'));
}
});
});
.container {
height: 690px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container" data-map="One">One</div>
<div class="container" data-map="Two">Tow</div>
<div class="container" data-map="Three">Three</div>
<div class="container" data-map="Four">Four</div>
<div class="container" data-map="Five">Five</div>
You'll need to use $(window).scrollTop(); as well as $that.outerHeight()
$(window).scroll(function() {
var windowScrollTop = $(this).scrollTop(); // window scroll top
$(".container").each(function() {
var $that = $(this);
var po = $that.offset().top;
var poHeight = $that.outerHeight(true); // the height of the element
var distanceTop = 100; // the distance from top to run the action .. it can be 0 if you want to run the action when the element hit the 0 top
if (windowScrollTop + distanceTop >= po && windowScrollTop + distanceTop <= po + poHeight) {
if(!$that.hasClass('red')){ // if element dosen't has class red
console.log($that.data('map'));
$(".container").not($that).removeClass('red'); // remove red class from all
$that.addClass('red'); // add red class to $that
}
}
});
}).scroll(); // run the scroll onload
.container {
height: 690px;
}
.container.red{
background : red;
color : #fff;
font-size: 30px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container" data-map="One">One</div>
<div class="container" data-map="Two">Two</div>
<div class="container" data-map="Three">Three</div>
<div class="container" data-map="Four">Four</div>
<div class="container" data-map="Five">Five</div>
I am trying to get all the HTML elements(div with particular id) which are there 500px below viewport on the page. I want to have this on scroll event.
var windowHeight = window.outerHeight;
var gridTop = windowHeight + 500;
var elements = document.getElementsByClassName('test');
window.addEventListener('scroll', function () {
for (let i = 0; i < elements.length; i++) {
var thisTop = elements[i].offsetTop - document.body.scrollTop;
if (thisTop >= gridTop) {
console.log('hi');
}
}
});
I need help on finding elements 500px below viewport.
EDIT:
I want to do it with pure JavaScript and I am using above code. But every time I am getting thisTop as 0. Please let me know the approach to do this.
Check following solution, here I put parent div which is scrollable.
Note- I have put offset of 50px, in order to support the example.
var parent = document.documentElement
var elements = document.getElementsByClassName('test');
var gridTop = parent.clientHeight + 50;
window.addEventListener('scroll', function() {
var printStr = "";
for (let i = 0; i < elements.length; i++) {
var thisTop = elements[i].offsetTop - parent.scrollTop;
if (thisTop >= gridTop) {
printStr += " "+elements[i].id
}
}
console.clear();
console.log('selected ', printStr);
});
.container div {
width: 40px;
height: 70px;
margin: 5px;
background-color: red;
text-align: center;
}
<div class="container">
<div class="test" id="1">1</div>
<div class="test" id="2">2</div>
<div class="test" id="3">3</div>
<div class="test" id="4">4</div>
<div class="test" id="5">5</div>
<div class="test" id="6">6</div>
<div class="test" id="7">7</div>
<div class="test" id="8">8</div>
<div class="test" id="9">9</div>
<div class="test" id="10">10</div>
<div class="test" id="11">11</div>
<div class="test" id="12">12</div>
</div>
You should not set multiple elements to have the same ID.
It will have a conflict in your js.
If you want to identify a set of DIVs, you should use CLASS instead.
Here, what I did was to find all elements classed as some-class-name iterated through the list,
Then get their width, both style.width and offsetWidth
<div id="the_900px_div" class="some-class-name" style="width:900px;border:1px solid blue;"></div>
<div id="the_200px_div" class="some-class-name" style="width:200px;border:1px solid blue;"></div>
<div id="the_100px_div" class="some-class-name" style="width:100px;border:1px solid red;"></div>
<script type="text/javascript">
function autorun()
{
var elements = document.getElementsByClassName('some-class-name');
var elementsLength = elements.length;
console.log(elements);
for (var i = 0; i < elementsLength; i++){
var sw = elements[i].style.width.replace('px','');
var ow = elements[i].offsetWidth;
var id = elements[i].id;
console.log(sw > 500)
console.log(id + ' style.width is ' + sw + 'px')
console.log(ow > 500)
console.log(id + ' offsetWidth is ' + ow + 'px')
}
}
if (document.addEventListener) document.addEventListener("DOMContentLoaded", autorun, false);
else if (document.attachEvent) document.attachEvent("onreadystatechange", autorun);
else window.onload = autorun;
</script>
Please have a look at my example.
I have multiple rows on my website and a scrollto() button, wich is always at the bottom of the screen.
Depending on where the usere is located on my site at a certain moment, I would like him to move to the next row after he clicked the button.
I am aware of how to make a user scrollto(), but I have no clue what kind of selector I should use.
function myFunction() {
var winScroll = window.scrollTop; // current scroll of window
// find closest div
var rows = document.querySelectorAll('.row');
var closest = rows[0]; // first section
var closest_idx = 0;
var min = closest.offsetTop - winScroll;
rows.forEach(function(row, index) {
var divTopSpace = row.offsetTop - winScroll;
if( divTopSpace < min && divTopSpace > 0 ) {
closest = row;
closest_idx = index;
min = divTopSpace;
}
});
var next_idx = closest_idx + 1;
if (next_idx == rows.length) {
next_idx = 0;
}
console.log(rows[next_idx]);
}
.rowOne {
height: 100vh;
background-color: peachpuff;
}
.rowTwo {
height: 100vh;
background-color: firebrick;
}
.rowThree {
height: 100vh;
background-color: deepskyblue;
}
.btn {
position: fixed;
bottom: 0;
left: 0;
right: 0;
height: 30px;
}
<div class="main">
<div class="row rowOne">
<div class="a">
<div class="b">
Foo
</div>
</div>
</div>
<div class="row rowTwo">
<div class="a">
<div class="b">
Bar
</div>
</div>
</div>
<div class="row rowThree">
<div class="a">
<div class="b">
Foobar
</div>
</div>
</div>
<button id="btn" class="btn" onclick="myFunction()">Button</button>
</div>
Thank you in advance.
Since they are all the same height (100% of the window height), the simple solution would be to simply scroll by that amount.
window.scrollBy(0, window.innerHeight);
Otherwise, you'll need to detect which element is the "current" one, and then get it's next sibling, and then scroll to it. Something like this (haven't tested, so syntax might be off, but this should give you an idea)
var winScroll = window.scrollTop; // current scroll of window
// find closest div
var rows = document.querySelectorAll('.row');
var closest = rows[0]; // first section
var closest_idx = 0;
var min = closest.offsetTop - winScroll;
rows.forEach(function(row, index) {
var divTopSpace = row.offsetTop - winScroll;
if( divTopSpave < min && divTopSpave > 0 ) {
closest = row;
closest_idx = index;
min = divTopSpace;
}
});
var next_idx = closest_idx + 1;
if (next_idx == rows.length) {
next_idx = 0;
}
window.scrollTo(rows[next_idx].scrollTop);
Edit: I finally come up with a bit different, but working version. Leaving link here for anyone who may need it in the future: https://jsfiddle.net/qmgob1d5/27/
I'm trying to make a gradient creator, that runs across 16 boxes. (which color values later going to be sent trough POST for server)
I got it working, to a point, Where I can select first and last color and make gradient. However, i couldn't figure out for the life of me, how to add more gradient points. eg: change color of any box and calculate gradient values between 3..4..5..etc points. like on this site: http://www.colorzilla.com/gradient-editor/
Here is fiddle set up with code: https://jsfiddle.net/qmgob1d5/11/
//Fill the gradient array with gray color.
var PaletteColors = Array.apply(null, Array(16)).map(function () { return {red:128, green:128, blue:128}; });
var ActiveBox = 0;
MakeGradient(); //run gradient maker at start
//Remove marker
$('.ColorPreview').contextmenu(function() {
$('#' + $(this).attr('id') ).css('border-bottom','0px');
return false
});
//Add marker and snap sliders to rgb values.
$('.ColorPreview').on('click',function() {
ActiveBox = $(this).attr('id');
ActiveBox = Number(ActiveBox.split('_')[1]);
$('#Color_' + ActiveBox).css('border-bottom','6px solid');
$('#red').val( PaletteColors[ActiveBox].red );
$('#green').val( PaletteColors[ActiveBox].green );
$('#blue').val( PaletteColors[ActiveBox].blue );
});
//Read values from sldier write them to PaletteColors array.
$('.Paletteslider').on('change mousemove',function() {
var red = ($('#red').val());
var green = ($('#green').val());
var blue = ($('#blue').val());
PaletteColors[ActiveBox].red = Number(red);
PaletteColors[ActiveBox].green = Number(green);
PaletteColors[ActiveBox].blue = Number(blue);
MakeGradient();
});
//Draw gradient based on PaletteColors array.
function MakeGradient() {
var FirstColor = PaletteColors[0];
var SecondColor = PaletteColors[15];
var end = 15;
var Count = 1/end;
for (i = 0; i <= end; i++ ) {
var Step = Count * i;
var CurrentRed = SecondColor.red * Step + FirstColor.red * (1 - Step);
var CurrentGreen = SecondColor.green * Step + FirstColor.green * (1 - Step);
var CurrentBlue = SecondColor.blue * Step + FirstColor.blue * (1 - Step);
PaletteColors[i].red = CurrentRed; PaletteColors[i].green = CurrentGreen; PaletteColors[i].blue = CurrentBlue;
$('#Color_' + i ).css('background-color','rgb('+ Math.round(CurrentRed) +','+ Math.round(CurrentGreen) + ',' + Math.round(CurrentBlue) +')');
}
}
any help or direction is welcome!
You can add the functionality you seek by adding trackers to the items in the PaletteColors array (id and edited properties), modifying the functionality of makeGradient, and adding a corresponding modification of edited to the Paletteslider event.
In order for additional markers to be added, you find a way to assess which colors have been modified or are the first/last colors in PaletteColors. I chose to filter an array on conditions if edited is true or the element is the first/last in array. From there, you can assign the values of FirstColor and SecondColor to the first and second color of PaletteColors, respectively.
To change the value of the FirstColor and SecondColor: inside the for loop, check if the id isn't the first or last element and if the SecondColor id equals i, and change the values of FirstColor/SecondColor if so. When assigning the colors to the various elements and creating the gradient, you can check whether i is equal to the FirstColor or SecondColor id property. If it is, use the current color of FirstColor or SecondColor gradient to allow it to show up, otherwise apply your transitional formula. See code snippet below for full working example.
//Fill the gradient array with gray color.
var PaletteColors = Array.apply(null, Array(16)).map(function(item, i) {
return { id: i, color: { red: 128, green: 128, blue: 128 }, edited: false }; });
var ActiveBox = 0;
MakeGradient(); //run gradient maker at start
//Remove marker
$('.ColorPreview').contextmenu(function() {
$('#' + $(this).attr('id')).css('border-bottom', '0px');
return false
});
//Add marker and snap sliders to rgb values.
$('.ColorPreview').on('click', function() {
ActiveBox = Number($(this).data('col'));
$('#Color_' + ActiveBox).css('border-bottom', '6px solid');
$('#red').val(PaletteColors[ActiveBox].color.red);
$('#green').val(PaletteColors[ActiveBox].color.green);
$('#blue').val(PaletteColors[ActiveBox].color.blue);
var a = PaletteColors.filter(function(col, i) {
return col.edited || i === 0 || i === 15;
}).map(function(item, i) {
item.count = i;
return item;
});
});
//Read values from sldier write them to PaletteColors array.
$('.Paletteslider').on('change mousemove', function() {
var red = Number($('#red').val());
var green = Number($('#green').val());
var blue = Number($('#blue').val());
if (!PaletteColors[ActiveBox].edited) {
PaletteColors[ActiveBox].edited = true;
}
PaletteColors[ActiveBox].color.red = red;
PaletteColors[ActiveBox].color.green = green;
PaletteColors[ActiveBox].color.blue = blue;
MakeGradient();
});
//Draw gradient based on PaletteColors array.
function MakeGradient() {
var colors = PaletteColors.filter(function(col, i) {
return col.edited || i === 0 || i === 15;
}).map(function(item, i) {
item.count = i;
return item;
});
var FirstColor = colors[0];
var SecondColor = colors[1];
var end = 15;
var Count = 1 / end;
for (i = 0; i <= end; i++) {
if (colors.length > 2 && i !== 0 && i !== 15 && SecondColor.id === i) {
FirstColor = SecondColor;
SecondColor = colors[SecondColor.count + 1];
}
var Step = Count * i;
var Current = {};
var str;
var match = FirstColor.id === i || SecondColor.id === i ? FirstColor.id === i ? 1 : 2 : false;
if (match) {
Current = match === 1 ? FirstColor.color : SecondColor.color;
} else {
Current.red = Math.round(SecondColor.color.red * Step + FirstColor.color.red * (1 - Step));
Current.green = Math.round(SecondColor.color.green * Step + FirstColor.color.green * (1 - Step));
Current.blue = Math.round(SecondColor.color.blue * Step + FirstColor.color.blue * (1 - Step));
}
PaletteColors[i].color.red = Current.red > 255 ? 255 : Current.red;
PaletteColors[i].color.green = Current.green > 255 ? 255 : Current.green;
PaletteColors[i].color.blue = Current.blue > 255 ? 255 : Current.blue;
str = 'rgb(' + [Current.red, Current.blue, Current.green].join(',') + ')';
$('#Color_' + i).css('background-color', str);
}
}
body, html{
background: #222222;
font-family: 'Lato', sans-serif;
color:white;
}
.ColorPreview {
background: rgb(0,0,0);
float: left;
height: 5em;
width: 6.25%;
border-bottom: 0px solid;
border-color: lightgrey;
}
#Color_0 {border-bottom: 0px solid;}
#Color_1 {border-bottom: 0px solid;}
#Color_2 {border-bottom: 0px solid;}
#Color_3 {border-bottom: 0px solid;}
#Color_4 {border-bottom: 0px solid;}
#Color_5 {border-bottom: 0px solid;}
#Color_6 {border-bottom: 0px solid;}
#Color_7 {border-bottom: 0px solid;}
#Color_8 {border-bottom: 0px solid;}
#Color_9 {border-bottom: 0px solid;}
#Color_10 {border-bottom: 0px solid;}
#Color_11 {border-bottom: 0px solid;}
#Color_12 {border-bottom: 0px solid;}
#Color_13 {border-bottom: 0px solid;}
#Color_14 {border-bottom: 0px solid;}
#Color_15 {border-bottom: 0px solid;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="PreviewTable" >
<div class="ColorPreview" id="Color_0" data-col="0">Color0</div>
<div class="ColorPreview" id="Color_1" data-col="1">Color1</div>
<div class="ColorPreview" id="Color_2" data-col="2">Color2</div>
<div class="ColorPreview" id="Color_3" data-col="3">Color3</div>
<div class="ColorPreview" id="Color_4" data-col="4">Color4</div>
<div class="ColorPreview" id="Color_5" data-col="5">Color5</div>
<div class="ColorPreview" id="Color_6" data-col="6">Color6</div>
<div class="ColorPreview" id="Color_7" data-col="7">Color7</div>
<div class="ColorPreview" id="Color_8" data-col="8">Color8</div>
<div class="ColorPreview" id="Color_9" data-col="9">Color9</div>
<div class="ColorPreview" id="Color_10" data-col="10">Color10</div>
<div class="ColorPreview" id="Color_11" data-col="11">Color11</div>
<div class="ColorPreview" id="Color_12" data-col="12">Color12</div>
<div class="ColorPreview" id="Color_13" data-col="13">Color13</div>
<div class="ColorPreview" id="Color_14" data-col="14">Color14</div>
<div class="ColorPreview" id="Color_15" data-col="15">Color15</div>
</div>
<div>
</div>
<div>
<p>
right click to remove marker
</p>
</div>
<div>
<p>red</p>
<span id="spanHueIndex"></span>
<p> <input class="slider Paletteslider" id="red" type="range" step="1" min="0" max="255" value="0" /></p>
<p>green</p>
<span id="spanSaturationIndex"></span>
<p> <input class="slider Paletteslider" id="green" type="range" step="1" min="0" max="255" value="0" /></p>
<p>blue</p>
<span id="spanLightnessIndex"></span>
<p> <input class="slider Paletteslider" id="blue" type="range" step="1" min="0" max="255" value="0" /></p>
</div>
I have and editable div that allow users to enter text. This is part of a chat widget so the design needs the box to be fixed to the bottom.
When a user types I need javascript to catch the resize and append classes to elements where needed.
I managed to get the box to resize upwards but I have had a lot of trouble scaling it back down again.
I have been stuck on this for days now, so any help now would be greatly appreciated.
I have the function and a basic UI version here JSFiddle
Its probably really simple but I am having no luck figuring this out
JSFiddle
var chatBoxSize = {
oldHeight : 0,
scrollHeight : 0,
lastClass : 1,
minClass : 1,
maxClass : 5,
min_height : 0,
last_size : 0,
getClass : function (size){
var sizes = [chatBoxSize.min_height, chatBoxSize.min_height * 2, chatBoxSize.min_height * 3, chatBoxSize.min_height * 4, chatBoxSize.min_height * 5];
switch (size){ case sizes[0] : return 1; break; case sizes[1] : return 2; break; case sizes[2] : return 3; break; case sizes[3] : return 4; break; case sizes[4] : return 5; break; };
//is not exact
var r = null;
console.log(size);
for(var x = 0; x < sizes.length; x++){
if(x < sizes.length){
if(size >= sizes[x] && size < sizes[(x + 1)]){
return (x + 1);
}
}
}
return chatBoxSize.maxClass;
}
};
$(function () {
chatBoxSize.min_height = parseInt($('#msgWriteArea').height());
chatBoxSize.max_height = chatBoxSize.min_height * 4;
chatBoxSize.last_size = chatBoxSize.min_height;
});
function updateChatSize() {
var id = '#msgWriteArea';
var element = document.querySelector(id);
var size = $(id)[0].scrollHeight;
var container = $('.container');
var toRemove = 'size_' + chatBoxSize.lastClass;
console.log(chatBoxSize.getClass(size));
chatBoxSize.lastClass = chatBoxSize.getClass(size);
console.log('Add new class', chatBoxSize.lastClass);
chatBoxSize.last_size = size;
$(id).removeClass(toRemove);
$(id).addClass('size_' + chatBoxSize.lastClass);
container.removeClass(toRemove);
container.addClass('size_' + chatBoxSize.lastClass);
$('#display').val('Removed ' + toRemove + ' Added ' + chatBoxSize.lastClass);
};
$(function (){
$('#msgWriteArea').bind('change keydown input', function () {
if(event.type == 'keydown'){
updateChatSize();
}
});
})
I have thought of just setting the heights to auto but that will not work with the rest of the ui elements.
Sorry to say but No JS needed at all
flex to the rescue, overflow-y: auto; and max-height to the editable DIV:
Heres a jsBin demo so you can play and resize the browser
*{box-sizing:border-box; -webkit-box-sizing:border-box;}
html, body{height:100%; margin:0;font:16px/1 sans-serif; color:#444;}
#chat{
display: flex;
flex-direction: column;
height:100%;
}
#messages{
flex:1;
overflow-y: auto;
}
#messages > div{
padding: 24px;
background: #eef;
margin: 4px 0;
}
#ui{
background: #eee;
}
#msgWriteArea{
padding: 24px;
overflow-y: auto;
height:100%;
background:#ddd;
max-height:100px; /* if max height is exceeded */
overflow-y: auto; /* add scrollbars */
}
<div id="chat">
<div id="messages">
<div>Message 1</div>
<div>Message 2</div>
<div>Message 3</div>
<div>Message 4</div>
<div>Message 5</div>
<div>Message 6</div>
</div>
<div id="ui">
<div id="msgWriteArea" contenteditable>Some text message</div>
</div>
</div>
Now, if you still really need to the the message area height (for some reasons) you could count the number of lines using JS.