Keep ratio of a div when the font size changes - javascript

I have a div with a fixed width and height and a font size of 16px like the following
<div id="mydiv" style="font-size:16px;height:40px;line-height:40px;width:160px;background:orange;text-align:center;">
hello world
</div>
I have an input text that allow changing the font size
<input type="text" id="input">
<button> change size </button>
JS :
$('button').on('click', function(){
var value = $('#input').val();
$('#mydiv').css('font-size', value + 'px');
});
If you enter a size of 30 for example the text will be out of the div, what I want to achieve is to keep the ratio, so when the font-size changes I want the div to change dimension keeping the aspect ratio. How I can do that ?
https://jsfiddle.net/mody5/x6t2dn3e/1/

You need to re-calculate the div width, height and line-height when you change its font-size. By updating just its font-size alone, nothing else will be changed.
$('button').on('click', function() {
var div = $('#mydiv');
// These methods return the value unit-less, so they'll be integers
// if defined.
var currentWidth = div.width();
var currentHeight = div.height();
// Parsing the values to make sure you got integers.
var currentFontSize = parseInt(div.css('font-size'), 10);
var currentLineHeight = parseInt(div.css('line-height'), 10);
var value = parseInt($('#input').val(), 10);
var newFontSize = value + 'px';
// Here we keep the ratio between width and height, considering
// the current and new font-size.
var newWidth = ((currentWidth * value) / currentFontSize) + 'px';
var newHeight = ((currentHeight * value) / currentFontSize) + 'px';
var newLineHeight = ((currentLineHeight * value) / currentFontSize) + 'px';
// Applying all the styles at once.
div.css({
fontSize: newFontSize,
width: newWidth,
height: newHeight,
lineHeight: newLineHeight
});
});
Demo

Why don't you just use em values ? This is exactly what it's used for: apply values relatively to a font-size…
.test {
font-size:16px;
height:2.5em;
line-height:2.5em;
width:10em;
background:orange;
text-align:center;
}
<div class="test">
hello world
</div>
Try change the font-size, you'll see all the div is growing. Use this website to help you calculate the good em values: http://pxtoem.com/
(And here's your update jsfiddle: https://jsfiddle.net/x6t2dn3e/9/ )

You could use a combination of inline-block and padding in your style.
Something like this:
display:inline-block;padding:15px
See updated fiddle here: https://jsfiddle.net/donal/p3hrctsf/2/
$('button').on('click', function(){
var value = $('#input').val();
$('#mydiv').css('font-size', value + 'px');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="mydiv" style="display: inline-block; font-size:16px;padding: 15px;background:orange;text-align:center;">
hello world
</div>
<br>
<input type="text" id="input">
<button>Change Font Size</button>

Related

js code for adding width of a class is not working

I want to change the width by adding 20%. My div class width in percentage. For example i have div with width 20%. I am using class name for stylesheet. When each time the page loading it want increase by 10%. The code is shown below. the avascript code document.getElementsByClassName("box")[0].style.width; is not working` proper. Please help me.
html
<div class="box">
var width = document.getElementsByClassName("box")[0].style.width;
var n = width + 20%;
width = n;
.box{
width:40%;
height:300px;
background-color:red;
}
<div class="box">
</div>
This line has a syntax error
width + 20%;
If you want to calculate percentage then
width = width + width*20/100;
Edit
As #Rory pointed out in the comments, your width value isn't getting set because width value isn't getting fetched correctly at first place, here is the updated code
var ele = document.getElementsByClassName("box")[0];
var width = parseInt(window.getComputedStyle(ele).width); //get computed style instead of style property
width = width + width*20/100;
document.getElementsByClassName("box")[0].style.width = width;
Edit 2
As pointed out by #Anant, if you want to increase with in percentage, then
var fn = (elem) => ((elem.offsetWidth/(elem.offsetParent || elem).offsetWidth)*100).toFixed(2)+'%' ;
var ele = document.getElementsByClassName("box")[0];
var width = parseInt(fn(ele)); //get computed style instead of style property
console.log(width);
//width = width + width*20/100;
width = (width + 20) + "%";
console.log(width);
document.getElementsByClassName("box")[0].style.width = width;
Demo
var fn = (elem) => ((elem.offsetWidth/(elem.offsetParent || elem).offsetWidth)*100).toFixed(2)+'%' ;
var ele = document.getElementsByClassName("box")[0];
var width = parseInt(fn(ele)); //get computed style instead of style property
console.log(width);
//width = width + width*20/100;
width = (width + 20) + "%";
console.log(width);
document.getElementsByClassName("box")[0].style.width = width;
.box{
width:40%;
height:300px;
background-color:red;
}
<div class="box">
</div>

Using getComputedStyle with border-box should return height sans border and padding

EDIT 3/Final: Th Computed Style problem/question is explained below but, for the benefit of others coming later, my real problem is solved with Flex Boxes and Vx measurements in conjunction with border-box. IMHO "display: flex;" is the answer to many questions and, although I'm struggling to get it to do what I want, stops you having to work against CSS!
EDIT 2: The following undoubtedly needs refactoring but if you can tell me that it does what I was asking for that'd be great. The change I had to make was to add clientTop in with offsetTop in the equation: -
function resizeContent()
{
var browserHeight = window.outerHeight;
var offesetHeight, offsetWidth;
var viewHeight = window.innerHeight;
var viewWidth = window.innerWidth;
var chromeFootPrint = browserHeight - viewHeight;
var tmpHeight = viewHeight;
if (window.matchMedia("(orientation: portrait)").matches) {
if (viewWidth > viewHeight) {
viewHeight = viewWidth - chromeFootPrint;
viewWidth = tmpHeight + chromeFootPrint;
}
} else {
if (viewWidth < viewHeight) {
viewHeight = viewWidth - chromeFootPrint;
viewWidth = tmpHeight + chromeFootPrint;
}
}
var dimTarget = logScroll;
var offsetTop = dimTarget.offsetTop + dimTarget.clientTop;
var offsetLeft = dimTarget.offsetLeft + dimTarget.clientLeft;
while (dimTarget = dimTarget.offsetParent) {
offsetTop += dimTarget.offsetTop + dimTarget.clientTop;
offsetLeft += dimTarget.offsetLeft + dimTarget.clientLeft;
}
logScrollHeight = viewHeight - (offsetTop + fireBreak);
logScroll.style.height = logScrollHeight + "px";
logScroll.style.width = getStyle(contentDiv).width;
logWindow.style.height = logScroll.style.height;
logWindow.style.width = logScroll.style.width;
logWindow.scrollTop = logWindow.scrollHeight - logScrollHeight;
contentDiv.style.visibility = "visible"; // Now we're presentable
}
and this is the fire-break calculation: -
var outerStyle = getStyle(wholeScreen);
fireBreak = Number(outerStyle.paddingBottom.match("[0-9.]*"))
+ Number(outerStyle.borderBottomWidth.match("[0-9.]*"))
;
resizeContent();
EDIT 1: Ok, let me re-phrase the question: - How to I find out the height of my DIVs content with: -
width: 250px;
border: 3px solid green;
padding: 0.5em;
box-sizing: border-box;
I am currently having to do this: -
logScrollHeight = viewHeight -
(offsetTop + Number(getStyle(headerDiv).paddingBottom.match("[0-9.]*")));
Original question: -
This is bound to be a duplicate but after nearly an hour of looking I have found many similar/identical questions but no real answer :-(
Why aren't the boundryWith and padding deducted from height?
Thankfully the boundryBottomWidth and PaddingBottom return have been converted to pixels (including the "px" string sadly) but doesn't the standard say that the usable height should be returned?
To get the height of an element, you don't use getComputedStyle.
getComputedStyle should only be used to get the parsed values that are currently applied from different style-sheets. In other words, you can see it as a live style-sheet, only targeted to a single element, with standardized units.
But in no way it should be used to get the current height or width of an element. Too many factors may interfere with the set value, and an element can even have an height without having any CSS height rule set.
So yes... when the height CSS rule is set to auto, you will get the computed value, which may coincide with the real height of the element, but it also may not be so.
So in order to get the displayed height of an element, without the border and padding, we will need to do some calculations ourself.
Element#getBoundingClientRect() will give us the real displayed dimensions of our element, transformations included. .offsetHeight will give us the untransformed height including the border-box, and .clientHeight will give us the untransformed height with the padding-box.
This means that we will first have to get all the border and padding computed values, then get the current scale of our element, and finally remove the scaled padding + border boxes from the values we get with getBoundingClientRect.
Here is an example, which will draw a new rectangle div atop the element's bounding-box without padding and border boxes.
let marker;
scale.onclick = e => {
element.classList.toggle('scaled');
drawRect();
}
boxSizing.onclick = e => {
element.classList.toggle('boxSized');
drawRect();
}
function drawRect() {
// remove previous marker if any
if (marker && marker.parentNode) {
marker.remove();
marker = null;
}
// first get the border and padding values
let computed = getComputedStyle(element);
let borderLeft = parseFloat(computed.borderLeftWidth);
let borderWidth = borderLeft + parseFloat(computed.borderRightWidth);
let borderTop = parseFloat(computed.borderTopWidth);
let borderHeight = borderTop + parseFloat(computed.borderBottomWidth);
let paddingLeft = parseFloat(computed.paddingLeft);
let paddingWidth = paddingLeft + parseFloat(computed.paddingRight)
let paddingTop = parseFloat(computed.paddingTop);
let paddingHeight = paddingTop + parseFloat(computed.paddingBottom);
// get the current bounding rect, including the border-box
let rect = element.getBoundingClientRect();
// we need to get the current scale since the computed values don't know about it...
let scale = 1 / (element.offsetHeight / rect.height);
// the real displayed height and width without border nor padding
let height = rect.height - ((borderHeight + paddingHeight) * scale);
let width = rect.width - ((borderWidth + paddingWidth) * scale);
// create our rectangle
marker = document.createElement('div');
marker.classList.add('marker');
marker.style.height = height + 'px';
marker.style.width = width + 'px';
// we need to scale border + padding again
marker.style.top = (rect.top + (borderTop + paddingTop) * scale) + 'px';
marker.style.left = (rect.left + (borderLeft + paddingLeft) * scale) + 'px';
document.body.append(marker);
}
#element {
width: 250px;
border: 0.5em solid green;
padding: 0.5em;
margin-top: 12px;
}
#element.scaled {
transform: scale(2);
transform-origin: top left;
}
#element.boxSized {
box-sizing: border-box;
}
.marker {
position: fixed;
width: 3px;
background: rgba(0, 0, 0, .3)
}
<label>scale
<input id="scale" type="checkbox">
</label>
<label>box-sizing
<input id="boxSizing" type="checkbox">
</label>
<div id="element">
Hello
<br> world
</div>
when you set box-sizing as border-box:
The width and height properties include the content, the padding and border, but not the margin
So when you use getComputedStyle to get a element's height, of course it includes the height of padding and border.
you can have a look at box-sizing property and css box model

Adapt width of texture to its content

I need to adapt the width of a textarea (='#overlay') to its content. The minimum width should be 100px:
'input #overlay': function(e) {
var overlay = $('#overlay'),
element = document.getElementById('overlay'),
pos = overlay.position(),
width = 100;
if (element.scrollWidth > element.clientWidth) {
var diff = Math.ceil((element.scrollWidth - element.clientWidth)/20)*20,
left = pos.left - (diff/2);
width = element.scrollWidth + diff;
overlay.css({left: left, width: width});
}
This code works to expand the textarea if there is a long line. But it can't be used to make it smaller if you delete some characters of the line.
You have to set the minimum value before the if-part:
overlay.css({ width: 100 });
Then the height will always be adapted to the needed height.

Square div with width based on percentage height

I'm trying to do the inverse of this fiddle, make a square with a width based on an a 100% based height.
http://jsfiddle.net/j372H/6/
<html style="height:100%">
<body style="height:100%">
<div id="square" style="background-color:black"></div>
</body>
</html>
$(window).ready(updateWidth);
$(window).resize(updateWidth);
function updateWidth()
{
var square = $('#square');
var size = square.width();
square.css('height',size);
}
Thank a lot for your help.
Seb.
In CSS set the height of the div also
<style>
html,body,#square { height:100%; }
</style>
then the reverse for your js function
function updateWidth()
{
var square = $('#square');
var size = square.height();
square.css('width',size);
}
Demo courtesy of wared - jsfiddle.net/wared/spSLP - - nice one, wared
$(window).ready(updateHeight);
$(window).resize(updateHeight);
function updateHeight()
{
var square = $('#square');
var size = square.height();
square.css('width',size);
}
NOTE - This needs the square div to have a height in the first place - height does not behave the same as width - just a heads up!
Using a simple math equation in the variable you can set a square div that re-sizes automatically.
change the 100 after * to give you a % width for your div.
see working jsfiddle for responsive width
$(document).ready(function() {
var height = ( $(window).height() / 100) * 100 ;
$('#square').width(height);
$('#square').height(height);
});
$(window).resize(function(){
var height = ( $(window).height() / 100) * 100 ;
$('#square').width(height);
$('#square').height(height);
});

Automatically adjusting font size to fit container

I have a defined style for div with fixed width and the text inside the div could have different lengths, like in this example. Is there any method using CSS and/or JS to adjust the text size in such a way that it will stay in bounds of the container?
this may work for you, try this
var originalFontSize = 12;
var divWidth = $('.cell').width();
$('.cell span').each(function(){
var spanWidth = $(this).width();
var newFontSize = (divWidth/spanWidth) * originalFontSize;
$(this).css({"font-size" : newFontSize, "line-height" : newFontSize/1.2 + "px"});
});​

Categories

Resources