I have an HTML page layout - something like this:
<div id='header'>
Header content
</div>
<div id='main_content'>
some content
</div>
The content in the #main_content div may be really long, or, next to nothing (i use it as part of a template across an entire site).
What I want is for it to minimally be the height of the viewport (minus the height of the header div above that - but no need to get that value, lets just use 100px for sake of discussion).
I can't seem to do this via pure CSS. However, I was thinking perhaps I can fire off a Javascript function every 1 second (and presumably fire it off on the resize event as well), check the height of #main_content, and if its not at least (viewport_hight - 100), then set it to be (viewport_height -100).
Problem is, I am not sure if this is do-able, and, not sure if there is a 'better way'.
Has anyone faced this issue and have a great solution?
Thanks.
Unfortunately, this is not possible with pure CSS. You will need to use JavaScript.
I'm unsure why you would need to call a JavaScript function every second. If it's called when a resize event is triggered and when the page loads, this should be sufficient.
Can you use the CSS min-height property? You can still calculate the value with javascript if necessary.
Take a look at this, I think it will help you:
http://www.xs4all.nl/~peterned/examples/csslayout1.html
this can be solved with CSS AND height=100% .. the following code demonstrates. the header here is 25px tall (works on all current browsers):
<div id='viewport' style='height:50%; padding-top: 25px; border: 4px solid green'>
<div id='header' style='margin-top: -25px'>
Header content
</div>
<div id="main_content" style='height: 100%; border: 1px solid red'>
some content
</div>
</div>
Thanks for the feedback. Here is what I wound up doing that worked:
Firs I used pure CSS for Firefox. For IE, used this jquery script (slightly modified for generic use)
$(document).ready(
function () {
// (I have some other not relevant code here as well in here)
if ( $j.browser.msie ){ setContentHeight(); }
}
);
function setContentHeight() {
// get viewport height
var viewportHeight = $(window).height();
// if body div is not tall enough, make it minimum height
if ( ( $('#body_content_div').height() - 275 ) < viewportHeight ) {
var desiredHeight = viewportHeight - 275;
$('#body_content_div').css("height", desiredHeight + "px");
}
// set this function to fire off 1x per second
// because ajax calls may re-populate the div at any time
setTimeout("setContentHeight()", 1000);
}
on document load it sets desired height
function gets called 1x per second to account for resizing and ajax (could have called on resize() event, but that would not account for ajax.
Related
I need to get the height of a textarea. Seemingly so simple but it's driving me mad.
I have been researching for ages on stackoverflow with no luck: textarea-value-height and jquery-js-get-the-scrollbar-height-of-an-textarea and javascript-how-to-get-the-height-of-text-inside-of-a-textarea, among many others.
This is how it looks currently:
This is how I want it to look, open a full height:
.
Here is my html:
<textarea id="history" class="input-xxlarge" placeholder="Enter the content ..." rows="13"></textarea>
CSS:
.input-xxlarge {
display: inline-block;
height: auto;
font-size: 12px;
width: 530px;
resize: none;
overflow: auto;
}
jQuery:
var textarea = $('#history');
I've tried (inter alia):
1. textarea.height() --> always returns 0
2. textarea.ready(function() { // wait for DOM to load
textarea.height();
}
3. getting scrollheight from textarea as an HTMLTextareaElement (i.e. DOM Element) --> returns 0
4. var contentSpan = textarea.wrapInner('<span>');
var height = contentSpan.height(); --> always returns 0
Please help, I'm at my wit's end!
Ok, I've found a solution. Whether it's the best solution, I don't know, but it works and that, frankly, is all I care about, having spent almost a day on this issue.
Here it is for anyone who faces the same problem:
Select the textarea:
var textarea = $('#history');
Get the textarea's text:
var text = textarea.text();
Create a temporary div:
var div = $('<div id="temp"></div>');
Set the temp div's width to be the same as the textarea. Very important else the text will be all on one line in the new temp div!:
div.css({
"width":"530px"
});
Insert the text into the new temp div:
div.text(text);
Append it to the DOM:
$('body').append(div);
Get the height of the div:
var divHeight = $('#temp').height();
Remove the temp div from the DOM:
div.remove();
Had a similar issue, in my case I wanted to have an expand button, that would toggle between two states (expanded/collapsed). After searching also for hours I finally came up with this solution:
Use the .prop to get the content height - works with dynamically filled textareas and then on a load command set it to your textarea.
Get the inner height:
var innerHeight = $('#MyTextarea').prop('scrollHeight');
Set it to your element
$('#MyTextarea').height(innerHeight);
Complete code with my expand button(I had min-height set on my textarea):
$(document).on("click", '.expand-textarea', function () {
$(this).toggleClass('Expanded');
if($(this).hasClass('Expanded'))
$($(this).data('target')).height(1);
else
$($(this).data('target')).height($($(this).data('target')).prop('scrollHeight'));
});
Modern answer: textarea sizing is a few lines of ES6 implementable two primary ways. It does not require (or benefit from) jQuery, nor does it require duplication of the content being sized.
As this is most often required to implement the functionality of auto-sizing, the code given below implements this feature. If your modal dialog containing the text area is not artificially constrained, but can adapt to the inner content size, this can be a perfect solution. E.g. don't specify the modal body's height and remove overflow-y directives. (Then no JS will be required to adjust the modal height at all.)
See the final section for additional details if you really, truly only actually need to fetch the height, not adapt the height of the textarea itself.
Line–Based
Pro: almost trivial. Pro: exploits existing user-agent behavior which does the heavy lifting (font metric calculations) for you. Con: impossible to animate. Con: extended to support constraints as per my codepen used to explore this problem, constraints are encoded into the HTML, not part of the CSS, as data attributes.
/* Lines must not wrap using this technique. */
textarea { overflow-x: auto; white-space: nowrap; resize: none }
for ( let elem of document.getElementsByTagName('textarea') ) {
// Prevent "jagged flashes" as lines are added.
elem.addEventListener('keydown', e => if ( e.which === 13 ) e.target.rows = e.target.rows + 1)
// React to the finalization of keyboard entry.
elem.addEventListener('keyup', e => e.target.rows = (elem.value.match(/\n/g) || "").length + 1)
}
Scrollable Region–Based
Pro: still almost trivial. Pro: animatable in CSS (i.e. using transition), though with some mild difficulty relating to collapsing back down. Pro: constraints defined in CSS through min-height and max-height. Con: unless carefully calculated, constraints may crop lines.
for ( let elem of document.getElementsByTagName('textarea') )
elem.addEventListener('keyup', e => {
e.target.style.height = 0 // SEE NOTE
e.target.style.height = e.target.scrollHeight + 'px'
})
A shocking percentage of the search results utilizing scrollHeight never consider the case of reducing size; for details, see below. Or they utilize events "in the wrong order" resulting in an apparent delay between entry and update, e.g. pressing enter… then any other key in order to update. Example.
Solution to Initial Question
The initial question specifically related to fetching the height of a textarea. The second approach to auto-sizing, there, demonstrates the solution to that specific question in relation to the actual content. scrollHeight contains the height of the element regardless of constraint, e.g. its inner content size.
Note: scrollHeight is technically the Math.max() of the element's outer height or the inner height, whichever is larger. Thus the initial assignment of zero height. Without this, the textarea would expand, but never collapse. Initial assignment of zero ensures you retrieve the actual inner content height. For sampling without alteration, remove the height override (assign '') or preserve (prior to) then restore after retrieval of scrolllHeight.
To calculate just the height of the element as-is, utilize getComputedStyle and parse the result:
parseInt(getComputedStyle(elem).height, 10)
But really, please consider just adjusting the CSS to permit the modal to expand naturally rather than involving JavaScript at all.
Place this BEFORE any HTML elements.
<script src="/path/to/jquery.js"></script>
<script>
$(document).ready(function(){
var textarea = $('#history');
alert(textarea.height()); //returns correct height
});
</script>
You obviously do not have to alert it. I was just using an easily visible example.
Given a textarea with an id of "history", this jQuery will return it's height:
$('#history').height()
Please see a working example at http://jsfiddle.net/jhfrench/JcGGR/
You can also retrieve the height in pixels by using $('#history').css('height'); if you're not planning on doing any calculations.
for current height in px:
height = window.getComputedStyle(document.querySelector('textarea')).getPropertyValue('height')
for current width in px:
width = window.getComputedStyle(document.querySelector('textarea')).getPropertyValue('width')
change 'textarea' to '#history' or like a css selector. or textarea, since a variable is declared to select element.
I have made a rediculasly small snippet to make a sub-header stick to the top.
But since , Like I said - I am by no means a js genious or jQuery genious - and actually far from it - I have my doubts about my own coding abilities..
the demo is here : http://jsfiddle.net/obmerk99/VvKq3/1/
The questions :
1 - there seems to be a lot of plugins (and a lot of questions also
in this very site) with much more code than my snippet - what am i
missing ?? What am I doing wrong ?
2 - will this work cross-browser ?
3 .. and this is a small problem, how to avoid the small "jump" that occurs ?
(if you go to the fiddle, and scroll slowly - you will see that the main div "jumps" when the script is evoked ..
I have tried to add another .pad class to the lower divs -
added class : .pad when script evoked.
.pad{padding-top:42px;}
but it does not seems to work right : http://jsfiddle.net/obmerk99/VvKq3/2/
5 .How can I calculate the real position of the div ? when I try
something like this :
var top = jQuery(window).scrollTop();
var div_top = jQuery('#header_stick').offset().top;
if (top > div_top) // height of float header;
it is jumpy ... http://jsfiddle.net/obmerk99/VvKq3/4/
6 any other suggestions are welcome..
The "jumping" occurs because the element was occupying space in the parent element, and when you change its position to fixed it's suddenly not anymore. I don't know the best way to handle it, but one option would be adding a small span (maybe with a single space) just before your #header_stick, with the same height of it, so when it's class is changed there will still be something there to account for the height difference. (Update: your pad solution is probably the best one, once done right; see below)
Your padding solution might also work, provided that: 1) you remember to remove that class when the user scrolls to the top (in your fiddle I see you adding it, but don't see you removing it); 2) You get the height right - I still couldn't look closely to your code, so I don't know where you got wrong. (Edit: the problem was that your .pad class was using the height of the floating header, not the stick header - fixing that and removing the class yielded what I believe to be the correct result)
About the real position of the div, have you tried subtracting the div's offset from the offset of the parent element? This way you'll have its position relative to the parent (pay attention to things like borders, though - I've recently answered another question where details like this mattered).
Update: your problem here seems to be that, when the position is changed to fixed, the offset also varies wildly. I'd suggest calculating the correct height, once, then storing it somewhere so the scroll function can use it. In other words, don't calculate it while scrolling, that makes it much more difficult to find the right theshold to do the class switch.
Other than that, I think you're code is fine, and I believe it will work cross browsers too (at least standards compliant ones; can't say anything about old versions of IE). Very insightful too, I always wondered how this "trick" worked, now I see it's simpler than I imagined...
You can try this way. I made a shorter version for easier analysis.
fiddle here
<div id="ontop">floating heading</div>
<header>sticky heading</header>
<div id="wrapper">
1<br/>2<br/>3<br/>4<br/>5<br/>6<br/>7<br/>8<br/>9<br/>10<br/>
</div>
#ontop {width:100%; height:80px; background-color:yellow;}
header {width:100%; height:20px; background-color:lightgrey; }
#wrapper {background-color:lightblue; height:5000px;}
.navfixed {position: fixed; top: 0px; z-index: 100; width:100%; display:block; margin-bottom:120px; }
.wrapperBelow{margin-top:22px;}
$(function () {
var elem = $('header'),
wrapperElem = $('#wrapper'),
elemTop = elem.offset().top;
$(window).scroll(function () {
elem.toggleClass('navfixed', $(window).scrollTop() > elemTop);
wrapperElem.toggleClass('wrapperBelow', $(window).scrollTop() > elemTop);
}).scroll();
});
I can't be the first to notice this but ever since 10.7 came out and they implemented the new style of scrollbars $(window).width() and $(window).height() no longer correctly return the size of the browser windows viewport....
Lets say you want to set a div the size of the browser window on load eh...
// load jquery //
<div id="bob">
</div>
<script>
$('#bob').width($(window).width()).height($(window).height());
</script>
and what ends up happening is something like this
To this I ask WTF?
here is an example of the issue
http://lab.aerotwist.com/webgl/a3/vertex-manipulation/
Do the elements containing #bob have margin or padding? If they do, that could be adding more space beyond the width and height of #bob, forcing scrollbars to appear.
If that's the problem, you could fix that by adding CSS like this:
html, body, #bob {
margin: 0;
padding: 0;
}
I have some simple javascript that I'm using to auto-adjust the width of elements on pages and to vertically center the text on these pages.
My script works, but in IE9 and a little in Safari there is a distinct moment where the elements are not resized and they jump across the page. It's just a momentary flash, but it bugs me as I'm generally not a "good enough" kind of person. Here is my own script:
$(document).ready(function() {
var containerwidth = $("#main_content").css("width");
var picwidth = $(".picture").css("width");
$(".picture").parent().css("width", picwidth);
var correctwidth = parseInt(containerwidth) - parseInt(picwidth);
$(".main-text").css("width",correctwidth-25);
if( $(".margins").css("width") ) {
$(".title").css("width", parseInt($(".width-set").css("width"))+10);
} else {
$(".title").css("width", parseInt($(".title").parent().css("width"))-10);
}
var container_height = $(".main-text").height();
var text_height = $(".vert-align").height();
var offset = (container_height - text_height) / 2;
$(".vert-align").css("margin-top", offset);
[...]
});
I realize the use of explicit offsets and whatnot is hackish, but I'm in a hurry and will correct it later. And yes, I am using jQuery.
This is stored in a file, and I've tried both calling it in the head, and also directly after the elements it affects, but the result is the same. Is this jitter just a fact of life for using element manipulation with javascript, or is there some solution I've missed on the forums?
Thanks!
I suspect the reason is because you are calling this in the $(document).ready(), which runs after the DOM is loaded (i.e. your elements are already displayed).
If you absolutely have to resize elements after they've loaded, the only thing I can think of that might help is having an overlay that covers the entire window, maybe something like:
#overlay{
position: fixed;
width: 100%; height: 100%;
background: #fff;
z-index: 9001;
}
And then hiding the overlay via $("#overlay").hide() after the resizing in your $(document).ready() function. I haven't tested this so I don't know if it works. You might have to add a short setTimeOut as well.
To be honest, though, this solution feels very dirty. Hopefully someone else can think of something more elegant.
#ZDYN is correct. The "flicker" happens when the page is displayed but the jQuery code has not been executed.
You can try to set in the css your elements to "visibility: hidden" so they will have their dimensions for the calculations, then change the visibility to "visible" after the resizing.
I have 2 divs. 1st div should automatically change own height if 2nd div height was changed.
var height = jQuery('#leftcol').height();
height += 20;
jQuery('.rightcol-botbg').height(height);
There is no ability to change HTML markup :(
I have many DHTML layout changes, so I can't run prev. code anytime.
I want to run it dynamically. I need to do something like event/trigger.
I tried to use jQuery('#leftcol').resize(function(){}) or jQuery('#leftcol').change(function(){}). but it doesn't work. (resize triggers when window size changes.)
When does your 1st div change ? Whatever triggers that should get the new div height, add 20 to it and set the height of the other div. Can you post some code samples ? If the size changes happen really frequently, a timer/interval that repeatedly checks one size and set's the other should also work, but this is less efficient.
I would monitor the other div using an interval then update accordingly
setInterval(function(){
var height = $('#leftcol').height();
if(height != $('#leftcol').data('oldHeight'))
{
$('.rightcol-botbg').height(height+20);
$('#leftcol').data('oldHeight',height);
}
},500)
(untested)
The above code checks for changes in height every 0.5 seconds, then updates .rightcol-botbg;
I don't understand JQuery, but seeming as this question is tagged Javascript I'll give you a Javascript solution
document.getElementById("yourDivID").style.height = "300px";
Edit - You want to know when the height of the div has changed?
I don't know if there is a better way for that, but I would approach it with a function:
function changeBlockHeight(divID, newHeight)
{
document.getElementById(divID).style.height = newHeight + "px";
blockHeightChanged(divID);
}
function blockHeightChanged(divID)
{
alert("Div " + divID + " has been changed in height!");
}
Somewhere in your code:
<div id="testBlock"></div>
<button onlcick="changeBlockHeight('testBlock')">Test</button>
Every time you change the blocks height, blockHeightChanged() is called.
well there is not any generic triggers for an element resize.
what is the cause of div's size change at your case? you can check your heights righta after or in that cause.
only alternative that i can think of is setting up a timer with setInterval and check both div sizes every once in a while.
var myInterval = self.setInterval("myCheckFunction()",1000);
function myCheckFunction() {
jQuery('.rightcol-botbg').height(jQuery('#leftcol').height());
}
Using an interval is not very browser friendly.
If you have a setup like this:
<div id="content">
<div id="tree">should be full height</div>
<div id="data">this one is half the height</div>
</div>
You could easily do this with css. I'm not sure if this is the case...
Otherwhise the solution proposed by Tom Gullen is the best one.
Use .bind() to create a custom event type, and then trigger that event using .trigger().
Here is a fiddle with an example (a bit contrived, but I think you will get the idea)