I have a text area that I want to change the font size of the text using a + and a - button.
I know how to get the font size to change using javascript/jquery. That all works great. However my problem is that as the font size grows it begins to stretch out of the text box. The top half of the first row will be tucked under the top bar of the text input area. I tried adjusting the line height proportionally to the increase in font size but it doesn't seem to solve the problem
here is my code:
HTML
<div style="color: #0D1E28">
-
<a href ="#" id="resetfont">
<span style="font-size: 9px; letter-spacing: -3px;">A</span>
<span style="font-size: 16px;">A</span>
</a>
+
</div>
<textarea name="txtOutput" id="txtOutput" style="width: 600px; height: 550px; line-height: 8.5; overflow: auto; font-size: 21.5px;" rows="2" cols="20" readOnly="readonly">
</textarea>
JavaScript
$(document).ready(function () {
$("#plustext").click( function () { resizeText(1); });
$("#minustext").click( function () { resizeText(-1); });
$("#resetfont").click(function () { $("#txtOutput").css('font-size', "14px"); });
});
function resizeText(multiplier) {
if ($("#txtOutput").css('font-size') == "") {
$("#txtOutput").css('font-size', "12px");
var currentFontSize = $("#txtOutput").css('font-size');
var currentFontSizeNum = parseFloat(currentFontSize, 10);
var newFontSize = (currentFontSizeNum + (multiplier * 0.5)) + "px"; ;
var currentLineHeight = $("#txtOutput").css('line-height');
if (currentLineHeight == "normal") {
currentLineHeight = "1";
}
var currentLineHeightNum = parseFloat(currentLineHeight, 10);
var newLineHeight = (currentLineHeightNum + (multiplier * 0.5));
$("#txtOutput").css('line-height', newLineHeight).css('font-size', newFontSize);
}
suggestions?
I made some mods to your code to get it to work on my end, I think it's cleaner and more efficient as well (see below). I haven't done a lot of testing but it seems to work in IE8 & FF.
IMO the line-height should adjust itself provided the line-height property is set to 'normal'. And I found that was exactly the case in Firefox. However, I did experience the problem you referenced in IE. In order to overcome it I had to replace the textarea with a clone of itself. Apparently, this forces IE to recalculate the proper line height. Hope this helps.
<script type="text/javascript">
$(document).ready(function () {
$("#plustext").click(function (e) { resizeText(1); e.preventDefault(); });
$("#minustext").click(function (e) { resizeText(-1); e.preventDefault();});
$("#resetfont").click(function (e) { $("#txtRegistryReportOuput").css('font-size', "14px"); e.preventDefault();});
});
function resizeText(multiplier) {
var textarea = $("#txtoutput");
var fs = (parseFloat(textarea.css('font-size')) + multiplier).toString() + 'px'; // Increment fontsize
var text = textarea.val(); // Firefox won't clone val() content (wierd..)
textarea.css({'font-size':fs}).replaceWith( textarea.clone().val(text) ); // Replace textarea w/ clone of itself to overcome line-height bug in IE
}
</script>
<div style="color: #0D1E28">
-
<a href ="#" id="resetfont">
<span style="font-size: 9px; letter-spacing: -3px;">A</span>
<span style="font-size: 16px;">A</span>
</a>
+
</div>
<textarea name="txtOutput" id="txtoutput" style="width: 600px; height: 550px; line-height: 8.5; overflow: auto; font-size: 21.5px;" rows="2" cols="20"></textarea>
This is one weird bug. By removing the node from the dom and re-inserting it, that seems to solve the problem.
$("#txtOutput").remove().appendTo("body");
http://jsfiddle.net/jyFfw/
Related
I have an element. We can call that Element A. I want Element A to have the same height as Element B with an additional height of 65px. For example if Element B has a height of 500px I want Element A to have a height of 565px
I am not very good at writing functions. I found one that can make Element A the same height as Element B but without the additional 60px.
$(document).ready(function() {
$("#ElementA").css("height", $("#ElementB").height());
});
Thanks!
Simply add the value wanted - 65 in this case
$(document).ready(function() {
$("#ElementA").css("height", $("#ElementB").height() + 65);
console.log("A:" + $("#ElementA").height() + "px");
console.log("B:" + $("#ElementB").height() + "px");
});
#ElementA {
background-color: red;
width: 10px;
}
#ElementB {
background-color: orange;
height: 20px;
width: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="ElementA">A</div>
<div id="ElementB">B</div>
You probably best doing it this way.
var SameHeights = function (){
var height = 0;
$('.allElements').each(function(index, element){
height = $(element).height() > height ? $(element).height() : height;
});
$('.allElements').height(height +65);
}
SameHeights();//call the function here, and re-use it again in the future.
Then on your HTML, you will have to add a class (it's better)
<div class="allElements">Element A</div>
<div class="allElements">Element B</div>
<div class="allElements">Element C</div>
<script>
$(document).ready(function() {
$("#ElementA").height( $("#ElementA").height() + 65 );
});
</script>
Here my solution
$(function(){
$("#ElementA").css("height", $("#ElementB").height()+65);
});
Here my responsive solution
$(function(){
$(window).resize(function(){
$("#ElementA").css("height", $("#ElementB").height()+65);
}).trigger('resize');
});
Pretty simple problem, but I can't find a solution. This plugin claims to do it, but I can't get it to work on my site at all, not as a called script, not inline, nothing. So, I have two columns of divs, the ones on one side larger than the other. I have set it up so the second column container will match the height of the first (which is determined elsewhere and thus varies) and set it to overflow:hidden, but what I want to do do is to remove the overflowing divs entirely so it always ends on the last complete div. Here's the fiddle: https://jsfiddle.net/bw2v39ru/2/
This is the JS to equalize the heights $('.row2').css('height', $('.row1').height()+'px');
In that example, only two of he block2 spans should be visible and the overflowing ones removed completely instead of leaving half a block.
Try this: https://jsfiddle.net/bw2v39ru/9/
Besides the code below - you will have to e.g. insert a <br style="clear:both;" /> in the parent DIV since the children has float: left
$('.row2').css('height', $('.row1').height());
var maxHeight = $("#main").outerHeight();
$("#main span").each(function() {
var elm = $(this);
if (elm.offset().top + elm.height() > maxHeight)
elm.remove();
});
as promised, here is my answer. Custom build jsfiddle from pure JavaScript.
https://jsfiddle.net/www139/vjgnsrpg/
Here is a code snippit for you. It assumes that all of your block2 elements have a fixed height. Also I changed the .row1 and .row2 classes to ids to make the solution easier to create. Feel free to change it back but remember to use document.getElementsByClassName('class')[i] instead.
//make sure you execute this script onload inside a jquery document ready or window.onload
//get the rendered height of both rows
//enter margin for blocks here
//this also assumes that the height of your block1 and block2 elements are fixed
var margin = 5;
var rowOneHeight = document.getElementById('row1').offsetHeight;
//get height of block2 element including vertical margin (multiplied twice)
var blockTwoHeight = document.getElementById('row2').getElementsByClassName('block2')[0].offsetHeight + 2 * margin;
var howManyBlocksCanFit = Math.floor(rowOneHeight / blockTwoHeight);
var numberOfBlocks = document.getElementById('row2').getElementsByClassName('block2').length;
for (var i = 0; i != numberOfBlocks - howManyBlocksCanFit; i++) {
document.getElementById('row2').removeChild(document.getElementById('row2').lastElementChild);
}
#main {
width: 240px;
}
#row1 {
float: left;
}
#row2 {
float: right;
overflow: hidden;
}
.block1 {
display: block;
margin: 5px;
width: 100px;
height: 50px;
border: 1px solid red;
}
.block2 {
display: block;
margin: 5px;
width: 100px;
height: 100px;
border: 1px solid red;
}
<div id="main">
<div id="row1">
<span class="block1"></span>
<span class="block1"></span>
<span class="block1"></span>
<span class="block1"></span>
<span class="block1"></span>
</div>
<div id="row2">
<span class="block2"></span>
<span class="block2"></span>
<span class="block2"></span>
<span class="block2"></span>
<span class="block2"></span>
</div>
</div>
Hope this helps you, please tell me if there was something I didn't understand in your question to improve my answer.
I programmed it for you, this works after your existing JS code line:
var row2 = $('div.row2'),
block2elements = row2.children('span.block2');
// Function to use also for other situations
function calculateElementsHeight(elements) {
var height = 0;
$.each(elements, function(i, elementRaw ){
height += $(elementRaw).height();
})
return height;
}
for(var i = 0; block2elements.length > i; i++) {
block2elements = row2.children('span.block2'); // Get new state of the block2 elements
if(row2.height() < calculateElementsHeight(block2elements)) {
block2elements.last().remove();
}
}
I can't quite find a clear answer on this, and excuse me if there is one I've missed.
I want my text input widths to automatically adjust to the size of the content within them. First with placeholder text than the actual text someone inputs.
I've created the below as an example. Currently, the boxes are far bigger than my placeholder text, causing huge amounts of white space, and it's obviously the same thing when I type in something.
I've tried width auto, some jQuery, and twine and bubble gum I found on the internet. But nothing has worked yet. Any thoughts? Thanks!
HTML:
<span><p>Hello, my name is </p></span>
<span><input type="text" id="input" class="form" placeholder="name"></span>
<span><p>. I am </p></span>
<span><input type="text" id="input" class="form" placeholder="age"></span>
<span><p> years old.</p></span>
CSS:
.form {
border: 0;
text-align: center;
outline: none;
}
span {
display: inline-block;
}
p {
font-family: arial;
}
Fiddle
One possible way:
[contenteditable=true]:empty:before {
content: attr(placeholder);
color:gray;
}
/* found this online --- it prevents the user from being able to make a (visible) newline */
[contenteditable=true] br{
display:none;
}
<p>Hello, my name is <span id="name" contenteditable="true" placeholder="name"></span>. I am <span id="age" contenteditable="true" placeholder="age"></span> years old.</p>
Source for CSS: http://codepen.io/flesler/pen/AEIFc.
You'll have to do some trickery to pick up the values if you need the values for a form.
Use onkeypress even
see this example :http://jsfiddle.net/kevalbhatt18/yug04jau/7/
<input id="txt" placeholder="name" class="form" type="text" onkeypress="this.style.width = ((this.value.length + 1) * 8) + 'px';"></span>
And for placeholder on load use jquery and apply placeholder
size in to input
$('input').css('width',((input.getAttribute('placeholder').length + 1) * 8) + 'px');
Even you can use id instead of input this is just an example so that I
used $(input)
And in css provide min-width
.form {
border: 1px solid black;
text-align: center;
outline: none;
min-width:4px;
}
EDIT:
If you remove all text from input box then it will take placeholder value using focusout
Example: http://jsfiddle.net/kevalbhatt18/yug04jau/8/
$("input").focusout(function(){
if(this.value.length>0){
this.style.width = ((this.value.length + 1) * 8) + 'px';
}else{
this.style.width = ((this.getAttribute('placeholder').length + 1) * 8) + 'px';
}
});
input.addEventListener('input', event => event.target.style.width = event.target.scrollWidth + 'px');
Unfortunately this will only increase the size of the input. If you delete characters the size will not decrease. For some use cases this is perfectly fine.
Kevin F is right, there is no native way to do it.
Here is a one way to do it if you really want it to happen.
In the code, there is an invisible span where the text is placed. Then we retrieve the width of the span.
https://jsfiddle.net/r02ma1n0/1/
var testdiv = $("#testdiv");
$("input").keydown( function(){
var ME = $(this);
//Manual Way
//var px = 6.5;
//var txtlength = ME.val().length;
//$(this).css({width: txtlength * px });
testdiv.html( ME.val() + "--");
var txtlength = testdiv.width();
ME.css({width: txtlength });
});
Try with 'size' attribute.
This will work even when you clear the text .
Need jQuery to work this
<div>
<input id="txt" type="text" style="max-width: 100%;" placeholder="name">
</div>
<script>
$(document).ready(function() {
var placeholderLen = $('#txt').attr('placeholder').length;
// keep some default lenght
placeholderLen = Math.max(5, placeholderLen);
$('#txt').attr('size', placeholderLen);
$('#txt').keydown(function() {
var size = $(this).val().length;
$(this).attr('size', Math.max(placeholderLen, size));
});
});
</script>
When an element contains inline-blocks which contain padding it doesn't get included in the width calculations of the element.
Essentially the same issue as jQuery outerWidth on a parent element which has child elements with padding.
This page should have text that lines up along the right side of the green box,
however the text will always grow larger than it's container, because width never includes the padding of any of it's children.
Is there a way to find the width of an element correctly without manually enumerating all child elements and re-adding the padding of each child? Same results when using .css('width'), .width() or .outerWidth().
<html>
<head>
<script src="http://code.jquery.com/jquery-2.1.0.min.js"></script>
<script>
jQuery(document).ready(function() {
var e = jQuery('#BLAH');
var pw = e.parent().width();
e.css('font-size','1px');
if (e.outerWidth() < pw) {
while ( e.outerWidth() < pw) {
alert('width ' + e.outerWidth() + ' < ' + pw);
e.css('font-size','+=1px');
}
e.css('font-size','-=1px');
}
});
</script>
<style>
#BLAH {
background-color: red;
white-space: nowrap;
}
.BLAH {
//padding: 0 10%;
background-color: blue;
display: inline;
}
</style>
</head>
<body>
<div style="background-color: green; width: 50%; height: 50%">
<div id="BLAH" style="display: inline-block;">
<div class="BLAH">BLAH</div>
<div class="BLAH">BLAH</div>
<div class="BLAH">BLAH</div>
<div class="BLAH">BLAH</div>
</div>
</div>
</body>
</html>
As the issue only occurs with percentage padding, you can instead use fixed pixel padding and increase that along with your font-size in the javascript. Something like this:
jQuery(document).ready(function () {
var e = jQuery('#BLAH');
var pw = e.parent().width();
e.css('font-size', '1px');
if (e.outerWidth() < pw) {
while (e.outerWidth() < pw) {
console.log('width ' + e.outerWidth() + ' < ' + pw);
e.css('font-size', '+=1px');
jQuery(".BLAH").css({
'padding-right': '+=1px',
'padding-left': '+=1px'
});
}
e.css('font-size', '-=1px');
jQuery(".BLAH").css({
'padding-right': '-=1px',
'padding-left': '-=1px'
});
}
});
http://jsfiddle.net/5Gufk/
If you wanted to get more sophisticated with it, you could calculate the padding as a percentage of the parent element's previous width and apply that rather than just increasing by one, or any other formula.
As for why it works this way, I was unable to find the part of the CSS spec that defines this behavior. However, it is important to understand that a percentage padding is based on the width of the containing block. Consider how it would work if you had 6 elements, all with 10% padding on both sides. That would be 120% padding, how could that even be possible for the padding of the elements to be 120% of the width of the parent element and still fit inside the parent?
Shrink wrapping a div to some text is pretty straightforward. But if the text wraps to a second line (or more) due to a max-width (as an example) then the size of the DIV does not shrink to the newly wrapped text. It is still expanded to the break point (the max-width value in this case), causing a fair amount of margin on the right side of the DIV. This is problematic when wanting to center this DIV so that the wrapped text appears centered. It will not because the DIV does not shrink to multiple lines of text that wrap. One solution is to use justified text, but that isn't always practical and the results can be hideous with large gaps between words.
I understand there's no solution to shrink the DIV to wrapped text in pure CSS. So my question is, how would one achieve this with Javascript?
This jsfiddle illustrates it: jsfiddle. The two words just barely wrap due to the max-width, yet the DIV does not then shrink to the newly wrapped text, leaving a nasty right-hand margin. I'd like to eliminate this and have the DIV resize to the wrapped text presumably using Javascript (since I don't believe a solution exists in pure CSS).
.shrunken {text-align: left; display: inline-block; font-size: 24px; background-color: #ddd; max-width: 130px;}
<div class="shrunken">Shrink Shrink</div>
It's not the prettiest solution but it should do the trick. The logic is to count the length of each word and use that to work out what the longest line is that will fit before being forced to wrap; then apply that width to the div. Fiddle here: http://jsfiddle.net/uS6cf/50/
Sample html...
<div class="wrapper">
<div class="shrunken">testing testing</div>
</div>
<div class="wrapper">
<div class="shrunken fixed">testing testing</div>
</div>
<div class="wrapper">
<div class="shrunken">testing</div>
</div>
<div class="wrapper">
<div class="shrunken fixed">testing</div>
</div>
<div class="wrapper">
<div class="shrunken" >testing 123 testing </div>
</div>
<div class="wrapper">
<div class="shrunken fixed" >testing 123 testing </div>
</div>
And the javacript (relying on jQuery)
$.fn.fixWidth = function () {
$(this).each(function () {
var el = $(this);
// This function gets the length of some text
// by adding a span to the container then getting it's length.
var getLength = function (txt) {
var span = new $("<span />");
if (txt == ' ')
span.html(' ');
else
span.text(txt);
el.append(span);
var len = span.width();
span.remove();
return len;
};
var words = el.text().split(' ');
var lengthOfSpace = getLength(' ');
var lengthOfLine = 0;
var maxElementWidth = el.width();
var maxLineLengthSoFar = 0;
for (var i = 0; i < words.length; i++) {
// Duplicate spaces will create empty entries.
if (words[i] == '')
continue;
// Get the length of the current word
var curWord = getLength(words[i]);
// Determine if adding this word to the current line will make it break
if ((lengthOfLine + (i == 0 ? 0 : lengthOfSpace) + curWord) > maxElementWidth) {
// If it will, see if the line we've built is the longest so far
if (lengthOfLine > maxLineLengthSoFar) {
maxLineLengthSoFar = lengthOfLine;
lengthOfLine = 0;
}
}
else // No break yet, keep building the line
lengthOfLine += (i == 0 ? 0 : lengthOfSpace) + curWord;
}
// If there are no line breaks maxLineLengthSoFar will be 0 still.
// In this case we don't actually need to set the width as the container
// will already be as small as possible.
if (maxLineLengthSoFar != 0)
el.css({ width: maxLineLengthSoFar + "px" });
});
};
$(function () {
$(".fixed").fixWidth();
});
I little late, but I think this CSS code can be useful for other users with the same problem:
div {
width: -moz-min-content;
width: -webkit-min-content;
width: min-content;
}
const range = document.createRange();
const p = document.getElementById('good');
const text = p.childNodes[0];
range.setStartBefore(text);
range.setEndAfter(text);
const clientRect = range.getBoundingClientRect();
p.style.width = `${clientRect.width}px`;
p {
max-width: 250px;
padding: 10px;
background-color: #eee;
border: 1px solid #aaa;
}
#bad {
background-color: #fbb;
}
<p id="bad">This box has a max width but also_too_much_padding.</p>
<p id="good">This box has a max width and the_right_amount_of_padding.</p>
I guess this is what you are thinking about, it can be done in css:
div {
border: black solid thin;
max-width: 100px;
overflow: auto;
}
You can see it here: http://jsfiddle.net/5epS4/
Try this:
https://jsfiddle.net/9snc5gfx/1/
.shrunken {
width: min-content;
word-break: normal;
}