Auto-resize elements based on container size without using scale - javascript

Example:
Just having a problem with the computation to auto adjust width of element-image and font size of the element-text based on the container's width. It's like,
$('.element-image').width() = $('.container').width() - $('.element-image').width();
$('.element-text').css('font-size') = $('.container').width() - $('.element-text').css('font-size');
<div class="container">
<img class="element-image" src="sample.jpg" />
<span class="element-text">Sample Text</span>
</div>
something like that but I can't get the logic. Can someone help? Note that this is for my web app, it's like an ad or graphic builder.
Here's the sample app:
https://drive.google.com/file/d/1dnsRg6TjLqUx6IzgLwOYq5uNJrrx7dUv/view?usp=drivesdk

Scaling images is trivial, just use percentage widths.
Scaling text is harder. You can use viewport units to scale the text based on the window size:
.element-text {
font-size: 10vw
}
<span class="element-text">Sample Text</span>
<div>Unscaled text (put this snippet in "fullscreen" mode and change the window size to see the effect)</div>
...but if you need text to scale to exact container sizes, you'll need to resort to javascript. The following is a (kind of dumb) method for setting the font-size to match the container size -- you wouldn't use short-interval polling in real life, and would probably do something smarter than simply incrementing / decrementing the font-size at each step, but this should suffice for demonstrating the technique:
window.setInterval(function() { // In real life you'd likely use the window resize event
var ewidth = $('.element-text').width();
var cwidth = $('.container').width();
var fontsize = parseInt($('.element-text').css("font-size"));
// change font size if the text block doesn't match the container width
if (ewidth > cwidth - 20) { // leave a little extra space to prevent jitter
$('.element-text').css("font-size", --fontsize);
} else if (ewidth < cwidth ) {
$('.element-text').css("font-size", ++fontsize);
}
}, 1);
.container {
resize: both;
overflow: hidden;
border: 1px solid;
width: 20px;
}
.element-image {
width: 100%
}
.element-text {
white-space: nowrap
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Resize me:
<div class="container">
<span class="element-text">Sample Text</span>
<img class="element-image" src="http://placehold.it/200x200" />
</div>
This jQuery plugin uses much the same technique. In its source code is the following comment block:
// I understand this is not optimized and we should
// consider implementing something akin to
// Daniel Hoffmann's answer here:
//
// http://stackoverflow.com/a/17433451/1094964
//
...which is maybe the most roundabout way I've ever discovered a potential question duplicate. (Clearly I need to pay more attention to the "related questions" list, because there it is right at the top of it...)

You dont have to do it with jquery. You can use CSS width:100%; or any percentage for that and it will generate a width accorind to its parent width.
Check this DEMO to understand.

I didnt really got what do you need but im fixing your jquery
var contwidth = $('.container').width();
var imgwidth = $('.element-image').width();
$('.element-image').width(contwidth - imgwidth);
$('.element-text').css('font-size',contwidth - imgwidth);
<div class="container">
<img class="element-image" src="sample.jpg" />
<span class="element-text">Sample Text</span>
</div>
btw as you are changing the width of the image, what is the logic of calculating container width - image width? This will be an error because as you trying to get the width of image the other function changes it. never ending cycle.

Related

Resizing a font with pure JavaScript based on string length

I know this question is asked multiple times, yet mine is different. I noticed that with the pure JavaScript solution, there is a need to resize the screen, while mine has absolutely nothing to do with resizing a screen.
What I have is a container div with some text in it. All texts have a certain font-size, but I want to change the font-size whenever the text gets a certain length.
I have seen this solution on SO:
Resize font depending on string length
Yet, this absolutely looks horrible in pure JavaScript and it's a post of three years ago. There surely must be a better (shorter, better) solution for this. I have read about the CSS solutions, but as I said: I am not using a certain viewport and I don't want to. I just want to change the font-size when it's too long.
I have made a JSFiddle to illustrate the problem:
https://jsfiddle.net/tpx71aqL/
<div class="test">
Blablabla
</div>
<div class="test">
Blablabla12124e121211asdasasas
</div>
PS: I can't use jQuery and don't want to use ellipsis.
An idea for this solution is actually really simple. Check out my codepen here.
Using a simple while loop which checks clientWidth against scrollWidth which you can learn more about here, we use the javascript .style.fontSize = "smaller" which decreases the font size by 1 unit. This works well when we don't know what unit is assigned in the CSS. You can read more about it here.
Hope this helps.
document.onreadystatechange = () => {
if (document.readyState === 'complete') {
var container = document.getElementById("test");
while (container.scrollWidth > container.clientWidth) {
container.style.fontSize = "smaller";
}
}
};
.test {
width: 200px;
border: 1px solid black;
font-size: 16px;
}
<div class="test">
Blablabla
</div>
<div class="test" id="test">
Blablabla12124e121211asdasasas
</div>
This fiddle shows what I suggested in my comment. You extract the current width of the text wrapper and reduce font size until you have a wrapper the same size or slightly smaller than the parent.
var fit = document.getElementById("fit"),
wrap = document.getElementById("wrap"),
step = 0.5,
currentSize;
while (fit.offsetWidth < wrap.offsetWidth) {
currentSize = parseFloat(window.getComputedStyle(wrap, null).getPropertyValue('font-size'));
wrap.style.fontSize = (currentSize - step) + "px";
}
Note the getComputedStyle to really get the calculated size.
You could improve this by making the reduction step smarter, instead of just going down a step again and again; for example calculate how far a 1px reduction approximated the wrapper width to the parent width and adjust step size accordingly.
Also this does assume that the text indeed needs scaling down, no scaling up - the same idea applies.
I needed something similar and I ended up doing something like this:
var elem = document.getElementById("test");
elem.style.fontSize = 30 - elem.innerHTML.length / 6 + 'px';
The idea is to set the max size and reduce it based on the length of the string.
Not fancy or sophisticated but worked for me.

Changing grid depending on device orientation

I'm trying to change the size of divs depending of screen size.
If the phone is laying it changes the sizes of divs.
Example:
block is default: 330px width and 250px high on a 768x1280 screen resolution.
The factor is:
width: 330px; factor x 2,18
height: 250px; factor x 5,12
When i change my phone to laying the sizes should be:
width: 587px
height: 150px
which doesnt work in the first place, can someone tell my why not?
js:
var devicewidth = $( window ).width();
var deviceheight = $( window ).height();
var mbwsize = devicewidth / 2.18;
var mbhsize = deviceheight / 5.12;
var mbisize = mbhsize / 1.25;
$('#mainmenublok').css('width', mbwsize+'px');
$('#mainmenublok').css('height', mbhsize+'px');
$('#mainmenublok').css('background-size', mbisize+'px'+mbisize+'px');
dont get errors, it just keeps the content in the middle as 720px width (768 - offset)
I changed the main div already here:
$('#maintable').css('width', devicewidth+'px');
Will try to change window to document but can someone look at this?
With document it doesnt change either.
The calculation is correct if you look at the picture at the debug.
I also tried it in a function but that did not work.
Added a picture to explain what happens
explain:
debug:
Based on the HTML provided by the author in the comments
<div onclick="bb.pushScreen('timeline.html', 'timeline');"class="mainmenublok" id="blocktimeline" style="background-image:url(ico/timeline.png); background-size:200px 200px; background-repeat: no-repeat; background-position:center;">
<img id="pictimeline" src="ico/bbaction.png" width="50" height="50" style="display:none;">
</div>
and the js used as shown above, I suggest to use $('.mainmenublok').css('width', mbwsize+'px'); instead of $('#mainmenublok').css('width', mbwsize+'px');. Dots are used to indicate classes in CSS, as hashtags are used to indicate ID's.
You could use mediaqueries or device.js?
The way you are trying to achieve by script.... Is okay but in some browser it may give you bugs ... better you try with any of the css frameworks like twitter bootstrap its not really huge.... the your site will be responsive as according to your device....

CSS or Javascript: How to fit two portrait images side by side in a container with fluid width?

I have a flexible .container with width:100%. I want to fit two portrait images (with varying widths) side by side into this `.container``
<div class="container">
<p>Some Text</p>
<img src="this-is-a-landscape-image.jpg" alt="test"/>
<p> Some Text again</p>
<img class="portait" src="this-is-a-portrait-image.jpg" alt="test"/>
<img class="portrait" src="this-is-a-portrait-image.jpg" alt="test"/>
</div>
The problem I have:
I'm working on a responsive-layout where this .container is flexible - width:100%.
However I want to be able to fit two images (that have the class .portrait) into this container side by side.
As you can see in this sample image, the two .portrait images are not necessarily the same width? I want them to be the same height, but the width should be dynamic (if they don't have the same ratio)
Is this somehow possible with pure css (maybe flexbox)? Or a little JS?
The contents are filled dynamically via a CMS, so that's the reason I can't hardcode it.
Any creative or helpful ideas?
I don't think there is a fully dynamic solution in pure css (though I would love to be proven wrong!)
I wrote a quick jQuery solution here: http://jsfiddle.net/d2gSK/2/
You can play with the image sizes, the window size, and the width of the gutter, and your height should stay the same for both images, while the width is set to proportion.
The javascript looks like this:
// put it in a function so you can easily reuse it elsewhere
function fitImages(img1, img2, gutter) {
// turn your images into jQuery objects (so we can use .width() )
var $img1 = $(img1);
var $img2 = $(img2);
// calculate the aspect ratio to maintain proportions
var ratio1 = $img1.width() / $img1.height();
var ratio2 = $img2.width() / $img2.height();
// get the target width of the two images combined, taking the gutter into account
var targetWidth = $img1.parent().width() - gutter;
// calculate the new width of each image
var width1 = targetWidth / (ratio1+ratio2) * ratio1;
var width2 = targetWidth / (ratio1+ratio2) * ratio2;
// set width, and height in proportion
$img1.width(width1);
$img1.height(width1 / ratio1);
$img2.width(width2);
$img2.height(width2 / ratio2);
// add the gutter
$img1.css('paddingRight', gutter + 'px');
}
//when the DOM is ready
$(document).ready(function() {
// cache the image container
var $wrapper = $('.portrait-wrapper');
// set the image sizes on load
fitImages($wrapper.children().get(0), $wrapper.children().get(1), 20);
// recalculate the image sizes on resize of the window
$(window).resize(function() {
fitImages($wrapper.children().get(0), $wrapper.children().get(1), 20);
});
});
I put the explanation inside the code. Feel free to ask if you want me to explain further.
Note that i put a wrapper around your images, and gave the images a display: block and a float:left, which is required to make this work!
You could do something like this.
<div class="container">
<p>Some Text</p>
<img src="this-is-a-landscape-image.jpg" alt="test"/>
<p> Some Text again</p>
<div class="portraits">
<img style="float:left;" class="portait" src="this-is-a-portrait-image.jpg" alt="test"/>
<img style="float:right;" class="portrait" src="this-is-a-portrait-image.jpg" alt="test"/>
</div>
</div>
Just add Float on them so they get out of the "normal flow", or you could even use position absolute, if the text between the top image and them stays the same at all times...
For the width: you can simply make their width in % as well so you can say give the first one 80% and the second 20% using pseudo classes...
another possibility would be that you make different hard coded css's where you can easily define at what page width you want to use what css, for example something like this:
#media screen and (max-width: 400px) {
.portrait:first {
width: 85px;
}
.portrait:last {
width: 105px;
}
}
and so on for every step on window size.
I Hope that helps :D

How to fit content of a DIV with fixed height

Consider that we have a DIV with fixed height. Without a defined width, the content will spread to the width of 100%. How to adjust the width to fill the DIV. Definitely, it is not posible with CSS, thus, I am looking for a solution with Javascript.
In this example, the text is spread across the width of 100% and leaves lots fo empty space in the fixed height. I need to set a width of 130px by javascript to fit the content to the entire DIV. But how to calculate the width?
NOTE: This value (130px) was estimated for the example text. Depending on the DIV content, javascript needs to calculate the width required to fit the content within the DIV.
Is there any way to estimate the 2D size of a DIV content?
CSS actually does this for height; when we have a fixed width, it continues the height to fill the DIV. Is it possible to do so for width too?
Clarification: How to vertically fill the DIV without knowing the width (we have a fixed height)?
If I understand your requirement correctly, you can do this using Javascript.
The trick is to use a helper <div> within which you let the browser flow the content to a specific width and see what height it comes up with. If the height of the helper <div> is more than that of the outer <div>, adjust the width to compensate.
Meanwhile, the outer <div> has overflow: hidden so all those flowing experiments don't produce jarring changes to your page layout.
See it in action.
This is an alternate approach.. While less efficient, it may be more accurate than my other answer.
see example here:
Basically loop the width down until the desired height is reached
<div id="AA">
<div id='A'>
I dont know how wide i am, I dont know how wide i am, I dont know how wide i am, I dont know how wide i am, I dont know how wide i need to be
</div>
</div>
The CSS:
#AA {
height: 300px;
border: 1px solid black;
width: 100%;
}
#A {
display: inline;
}
The Script:
height = $('#AA').height();
minWidth = 300;
currentWidth = $('#A').width();
currentHeight = $('#A').height();
stop = false;
if (currentWidth >= minWidth) {
while (stop === false) {
if (currentWidth >= minWidth) {
newWidth = currentWidth - 1;
$('#AA').width(newWidth);
currentHeight = $('#A').height();
currentWidth = $('#A').width();
if (currentHeight < height) {
stop = false;
}
else {
stop = true;
}
}
else {
stop = true;
}
}
}

Positioning an image based on its height/width

I'm working on a simple script that acts as a slideshow.
It's based on this script.
Background:
Most of these types of scripts (including the more advanced ones) have the issue that they work great with landscape-style images but really mess portrait-style images up. So I'm trying to build something more or less from scratch.
Problem
I want my images centered on the page. So I use position:absolute; and left:50%; and top:50%; which puts left-most and top-most edge of the image in the proper position. But to center it you would need to do left:50% - imageWidth/2 (which obviously doesn't exist in CSS)
So I need to use javascript to get the image height/width and change it's left and top positioning as needed.
Here is my HTML:
<div class="fadewrapper">
<div class="fadein">
<img src="../Content/images/samples/1.jpg">
<img src="../Content/images/samples/2.jpg">
<img src="../Content/images/samples/3.jpg">
</div>
</div>
Here is my CSS:
.fadewrapper {width:100%; height:100%;}
.fadein { display:inline-block;}
.fadein img {position:absolute; top:50%;}
My knowledge in javascript is limited, but I've found this script (on SO):
var img = new Image();
img.onload = function () {
alert(this.width + 'x' + this.height);
}
img.src = 'http://www.google.com/intl/en_ALL/images/logo.gif';
This script works, but I don't know how to use the images on my page and how to then adjust its positioning. Any and all help is very much appreciated.
Here you go. This will set the image in the exact center of the wrapper.
win_width = $('#fadewrapper').width();
win_height = $('#fadewrapper').height();
border = $('#framewrapper').css('borderWidth');
$('.fadein img').each(function(){
$(this).css({
'left' : (win_width - $(this).width() - border ) / 2,
'top': (win_height - $(this).height() - border ) / 2
});
})
Here's a jsFiddle working example. It reacts based on the window size. Resize the output window to see it react
This might be worth of trying:
<DIV style="position:relative;top:100px;height:300px;text-align:center;white-space:nowrap">
<IMG id="your_img_id_1" src="your_img_source" height="100%">
<IMG id="your_img_id_2" src="your_img_source" height="100%">
<IMG id="your_img_id_3" src="your_img_source" height="100%">
</DIV>
Add these positioning rules to your fadewrapper-class, and remove all others. Then make changes needed to top and height values, but don't change the height-attribute values in IMG-elements. IDs can be omitted, if you don't need them.
EDIT:
I'm sorry, I didn't notice to check window resize. Code corrected. Width's shoul'd be OK with smaller window sizes now.
I've tested this in IE, FF, Opera and Chrome. In all those browsers images appear just like I want to. But if I've missunderstood what you'd like to have?

Categories

Resources