Automatically resizing div - javascript

This is another of the infinite questions about how to get div sizing to behave, but conversely I haven't been able to find a sufficiently similar question to get my particular case working.
function update() {
$('#container .body-text').bigText({verticalAlign:'top',whiteSpace:'pre'});
}
function doresize(form) {
var container = $('#container')[0];
container.style.height = form.height.value + 'px';
setTimeout(500, update);
}
function dotext(form) {
$('#container .body-text').text(form.text.value);
update();
}
update();
.container {
float: left;
border: solid 1px black;
position: relative;
margin-left: 5px;
width: 20%;
height: 200px;
padding: 2px;
}
.header {
width: 100%;
height: 64px;
background-color: blue;
}
.body {
width: 100%;
height: 100%;
max-height: calc(100% - 64px);
background-color: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<script src="https://rawgithub.com/DanielHoffmann/jquery-bigtext/master/jquery-bigtext.js"></script>
<form name="setup">
<label>Set height: <input type="number" name="height" value="200" /></label>
<button type="button" onclick="doresize(this.form)">Resize</button><br />
<label>Set text: <textarea name="text">Multi-Line
Text</textarea></label>
<button type="button" onclick="dotext(this.form)">Change</button><br />
</form>
<br />
<div id="container" class="container" onload="update()">
<div class="header"></div>
<div class="body"><div class="body-text">Multi-Line
Text</div></div>
</div>
The above snippet shows a fairly basic layout with a container div with a width and height that are controlled by outside forces. (In the real code this is controlled by the browser window resizing, but I've put in a basic form height adjustment here for demonstration purposes.)
What I'm trying to achieve with this is the following:
Both internal divs fill to 100% width of their parent.
The top (blue) div has a fixed height.
The bottom (green) div will use the remaining space in the parent by default.
However, after a bit of existing JS code resizes the font size of the text to best-fit this space (both width and height)...
If the container is tall enough and the text is short enough that there's extra space below, then the green div should vertically shrink to fit its text and both the blue and green divs should then appear vertically centred in the container div.
If the container size or the text changes, repeat the process of fitting the text and recentering.
I know how to do most of the pieces individually, I'm just not sure how to put it all together, and whether step 5 is possible with CSS or whether it requires JS. (I've tried adding the vertical centering with CSS via the absolute-translate-50% trick, which works great at tall container sizes or text that is wider than it is tall, but not the other way around -- the text overflows the green div because the height is not fixed so can't be taken into account by the font sizing script.)
I'm ok with rearranging or inserting additional divs if this is required.
EDIT: the following snippet inspired by Shadi's answer seems to do the trick:
function update() {
var text = $('#container .body-text');
text.parent().parent().css('height', '100%');
text.parent().css('height', '100%');
text.bigText({verticalAlign:'top',whiteSpace:'pre'});
text.parent().css('height', text.height());
text.parent().parent().css('height', text.height() + 64);
}
function doresize(form) {
$('#container').css('height', form.height.value);
update();
}
function dotext(form) {
$('#container .body-text').text(form.text.value);
update();
}
update();
.container {
float: left;
border: solid 1px black;
margin-left: 5px;
width: 20%;
height: 200px;
padding: 2px;
}
.subcontainer {
position: relative;
width: 100%;
height: 100%;
top: 50%;
transform: translateY(-50%);
}
.header {
width: 100%;
height: 64px;
background-color: blue;
}
.body {
width: 100%;
height: 100%;
max-height: calc(100% - 64px);
background-color: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<script src="https://rawgithub.com/DanielHoffmann/jquery-bigtext/master/jquery-bigtext.js"></script>
<form name="setup">
<label>Set height: <input type="number" name="height" value="200" /></label>
<button type="button" onclick="doresize(this.form)">Resize</button><br />
<label>Set text: <textarea name="text">Multi-Line
Text</textarea></label>
<button type="button" onclick="dotext(this.form)">Change</button><br />
</form>
<br />
<div id="container" class="container">
<div class="subcontainer">
<div class="header"></div>
<div class="body"><div class="body-text">Multi-Line
Text</div></div>
</div>
</div>
Try values between 80 and 300 to see it in action.

I have tried this in a code, please would you try it and see if it fits your need, the following code will make the green div fullfil the remining container height, and then after calcuating the text size and width it shrinks to fit the new text height
function update() {
$('#container').css('height', '200px' /*this would be dynamic based on the container height*/);
$('#container .body-text').bigText({ verticalAlign: 'top', whiteSpace: 'pre' });
$('#container').css('height', $('#bodytxt').height() + 64 /*this is the header height - blue div*/);
}
You need also to add an id for your bodytext div:
<div id="bodytxt" class="body-text">Multi-Line Text</div>

Related

Scroll smoothly by 100px horizontally

Heyjo,
problem: I am looking for a javascript or jQuery code since a week to get an implemented scrollbutton on my website working. The moment I fail is when the button should work multiple times: his task is not so scroll to a dedicated element, it should scroll left by, for instance, 100px. Furthermore the scrolling is supposed to happen smoothly (in other words, animated) in a proper section.
what I tried: til now I tried to fulfill this task with $('#idofsection').animate({scrollLeft: 100}, 800) but obviously it didn't work. The Problem was, one couldn't use it multiple times, it just scrolled to a position in my section. Afterwards I used javascript's scrollBy(100, 0) or scrollLeft += 100px, but unfortunately didn't got it to scroll smoothly.
I hope someone can help me because I spent so much time on this issue without finding a solution. Thanks a lot, Sven
You can use scrollBy(100, 0) just like you tried and add this css property to the viewport where you want to scroll:
scroll-behavior: smooth;
.window{
width: 200px;
height: 100px;
border: 1px red solid;
overflow: hidden;
scroll-behavior: smooth;
}
.container{
width: 1000px;
height: 200px;
}
.buttons{
width: 200px;
display: flex;
flex-direction: row;
justify-content: space-between;
}
<div id="window" class="window">
<div class="container">
fjsdlf jslkd flsakj flksad jflkjsa dlfj slakd jflskad flksdaj lfk sadlkfj asldk fslkad fjlkasd flksa jdlf jsadlkfj slkda jflksadj flksa jdlkfj sadlk jflksadj flksjadflksadj flksdaj flksdaj flksdaflksjdflk sjdalkfj skdal fjlksadj flksa fklsjadfklj sadklfj salkdjf lksadj flksjad lfkj sadlkf jslakdjf lksdaj flkasj flkjsa dlfskal flsa jdas lkfjskad fj
</div>
</div>
<div class="buttons">
<button onclick="document.getElementById('window').scrollBy(-100,0)">
<-
</button>
<button onclick="document.getElementById('window').scrollBy(100,0)">
->
</button>
</div>
Solution also here: JSFiddle
So use the animation properties += to adjust it from current position.
$("#next").click(function(){
$('#foo').stop().animate({scrollLeft: "+=100"}, 800);
return false;
});
div {
width: 200px;
overflow: auto;
padding: 1em;
border: 1px solid black;
}
div p {
width: 1000px;
border: 2px dashed #000;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="foo">
<p>TEST</p>
</div>
<button id="next">Next</button>

Margin issue with jquery load()

I am loading html page inside a div with jquery. It does work fine.
var loginBtn = $("#loginBtn");
var loginPage = $("#login");
var submitBtn = $("#submitBtn");
var submitPage = $("#submit");
var checkBtn = $("#checkBtn");
var checkPage = $("#check");
loginPage.load( "login.html" );
submitPage.load( "submitPoints.html" );
checkPage.load( "checkPoints.html" );
body {
margin: 0 !important;
padding: 0 !important;
background-color: white;
}
#mainFrame {
width: 100%;
height: 300px;
background-color:cadetblue;
padding-top: 0;
margin-top: 0px;
position: relative;
}
<div id="mainFrame">
<div id="login"></div>
<div id="check"></div>
<div id="submit"></div>
</div>
My issue is that if the loaded html has no content, the margin between the parent document body (white) and the top of the loaded html (green) is none (that's what I want, it's ok).
However as soon as I add content to the loaded html, a gap is generated at the top of the page :\
I thought it was all about setting some line-height prop in the css but it seems helpless.
Any ideas what I am doing wrong ?
What you are seeing is the top margin of the first piece of content overflowing its container (also known more commonly as margin collapsing):
body {
background:yellow;
}
#container {
background:green;
height:300px;
}
<div id="container">
<h1>I have a top margin of 1em by default that is overflowing into the body.</h1>
</div>
If you give your container element a padding of that same amount, the margin space of the body won't be used and the element will be pushed down in the green area.
body {
background:yellow;
}
#container {
background:green;
height:300px;
padding:1em;
}
<div id="container">
<h1>I have a top margin of 1em by default that is now contained within my parent.</h1>
</div>
Or, you could set the top margin of the first piece of content to zero:
body {
background:yellow;
}
#container {
background:green;
height:300px;
}
#container > h1:first-child { margin-top:0; }
<div id="container">
<h1>My top margin has been set to zero.</h1>
</div>
Finally, you could set the overflow of the content area to auto but (although this seems to be the popular answer), I don't prefer this approach as you run the risk of unintended fitting of the content as the content changes and/or the container size changes. You give up a bit of sizing control:
body {
background:yellow;
}
#container {
background:green;
height:300px;
overflow:auto;
}
<div id="container">
<h1>The content area has had its overflow set to auto.</h1>
</div>
When you load new content it gets rendered in the document and those new elements might have properties. In this case, most probably the Login has a margin value. Another option is that it has a class or some selector that is being picked up by a CSS file which appends the margin to it.
Easiet way would be to right-click on the Login element, choose inspect, and analyze the style of the element with web-dev / style.
If you want to keep the margin on the inner content, you should set an overflow. Look what happens when we remove the overflow: auto line from .content > div (try clicking the box after running the code sample below).
This is because of margin collapsing. The margin on the inner content is combined with the margin on the outer element and applied on the outer element, i.e. two margins of the two elements are collapsed into a single margin.
document.querySelector('.content').addEventListener('click', (e) => {
e.target.classList.toggle('overflow');
});
html,
body {
margin: 0;
padding: 0;
}
.outer {
width: 200px;
background: red;
}
.content > div {
width: 100%;
height: 300px;
background: cadetblue;
cursor: pointer;
}
.content > div.overflow {
overflow: auto;
}
.test {
margin: 10px;
display: block;
}
<div class="outer">
<div class="content">
<div><span class="test">Test</span></div>
</div>
</div>

Centering two buttons into child div of a parent div

I am using dat.gui.js to have a parameters menu with Three.js. I would like to put this menu on the top-right of main window. Moreover, I would like to add 2 buttons at the bottom of this menu which have to be centered horizontally and relatively to the parent div.
Here's an example in JS Fiddle.
As you can see, into HTML, I have the following structure for child and parent div:
<div id="webgl">
<div id="global-ui">
<div id="gui">
</div>
<div id="buttons">
<button type="button" id="startButtonId" class="btn btn-primary" tabindex="13">Start Animation</button>
<button type="button" id="resetButtonId" class="btn btn-default" tabindex="14">Reset</button>
</div>
</div>
</div>
with the CSS for #gui:
gui.domElement.id = 'gui';
which corresponds to:
#global-ui {position: relative;}
#gui {position: absolute; top: 0; right: 0;}
#buttons {position: absolute; top: 200px;}
#global-ui div represents the parent div of #gui div and #buttons div.
With this css, I get the following image:
and I would like to get this:
As you can see on the first image, there are 2 issues : first, the DAT.GUI is not located strictly on the right and top even with CSS "#gui {position: absolute; top: 0; right: 0;}". It seems there is a margin on the right.
Second problem, the two buttons are not centered relatively to DAT.GUI, I tried using "margin: 0 auto;" or with "text-align: center;" but without success. I want to center it relatively to #gui div container and with an automatic way.
How can I solve these two issues?
As for the spacing to the right of the controls, your #gui element has a right margin of 15px, so you can correct this by adding margin-right:0; to the CSS rules for #gui:
#gui {position: absolute; top: 0; right: 0; margin-right:0;}
As for aligning the elements to be centered, I've broken it down here:
Theory
In order to center something like div, the way to do it with CSS is to have the child element use margin-right and margin-left both set to auto, and the parent element needs to be wide enough to fill the area area you want the containers to be centered inside.
Solution
The width of the container (in this case #buttons) is only as wide as the buttons inside it make it, so there's not enough width for the buttons to be able to be centered if you were to simply do this:
#button {
margin-left: auto;
margin-right: auto;
}
Therefore, the width #buttons container has to be increased so that it is as wide as you need it to be, in this case, to be as wide as the #gui element, but doing just that still doesn't let the buttons be centered because there are two of them, so you need a wrapper element inside which creates space inside for the buttons to center within. This looks like this in the DOM:
<div id="buttons-wrapper">
<div id="buttons">
<button type="button" id="startButtonId" class="btn btn-primary" tabindex="13">Start Animation</button>
<button type="button" id="resetButtonId" class="btn btn-default" tabindex="14">Reset</button>
</div>
</div>
And then #buttons-wrapper needs to be set to the width of #gui (the target width of the space which the buttons should be centered), and #buttons needs to be set to a width which is equal to the sum of the child containers #startButtonId and #resetButtonId, and then margin-right and margin-left can finally be applied to #buttons and it will work as expected.
To set the width dynamically, you've got to use JavaScript and measure the widths of the containers you need:
document.getElementById('buttons-wrapper').style.width = gui.width + 'px';
target_width = 5; // a couple pixels extra
target_width = target_width + document.getElementById('startButtonId').offsetWidth;
target_width = target_width + document.getElementById('resetButtonId').offsetWidth;
document.getElementById('buttons').style.width = target_width + 'px';
I've put the complete solution for your specific case into this fiddle: http://jsfiddle.net/bnbst5sc/4/
Generic Solution
Here it is outside the context of your solution, as a general case:
#outer-wrapper {
position: absolute;
top: 100px;
left: 150px;
width: 300px;
padding: 10px 0;
background-color: #ff0000;
}
#inner-wrapper {
margin-left: auto;
margin-right: auto;
width: 175px;
padding: 10px 0;
background-color: #00ff00;
}
button {
display: inline-block;
float: left;
}
#btn1 {
background-color: #f0f000;
width: 100px;
}
#btn2 {
background-color: #00f0f0;
width: 75px;
}
<div id="outer-wrapper">
<!-- #outer-wrapper, has an arbitrary width -->
<div id="inner-wrapper">
<!-- #inner-wrapper, as wide as the sum of the widths of #btn1 and #btn2 and has margin-left and margin-right set to auto-->
<button id="btn1">Button 1</button>
<button id="btn2">Button 2</button>
</div>
</div>

Resizing one element using jQuery UI changing the position of another

I am trying to make resizible and draggable lines out of labels using jQuery UI.
The problem is, if I add two labels and try to resize the first label, it changes the position of the second label (but if I resize the second label it does not change the position of the first label).
How to prevent labels from changing other label's position while resizing..?
HTML:
<div id="main">
<button id="s">add line</button>
</div>
<div id="line" class="hidden">
<label class="dra"></label>
</div>
JS:
function makeline() {
$t = $(".dra", "#line").clone(true).draggable().resizable({
handles: "s, n"
});
$("#main").append($t);
}
$("#s").click(function () {
makeline();
});
CSS:
.dra {
display: block;
background-color:red;
width: 7px;
height: 80px;
border: 1px solid red;
}
.hidden {
display: none;
}
#main {
border: 1px solid black;
width:500px;
height: 300px;
}
UPDATE: Full code in JSFiddle
This is happening because the jQuery UI widgets set the position of element to relative by default, leaving it in the normal flow of the document. You can work around this issue by applying position:absolute for the elements like:
.ui-resizable {
position:absolute !important;
}
This will cause them to stack on top of each other rather than one below another since they aren't in the normal flow anymore. You can easily fix this using the jQuery ui position() utility method as shown below:
$("#s").click(function() {
$t = $("#line .dra").clone(true).draggable().resizable({
handles: "s, n"
})
if ($("#main").find(".dra").length) {
$t.position({
at: "left bottom",
of: "#main .dra:last"
})
};
$("#main").append($t);
});
.dra {
display: block;
background-color: red;
width: 7px;
height: 80px;
border: 1px solid red;
}
.hidden {
display: none;
}
#main {
border: 1px solid black;
width: 500px;
height: 300px;
}
.ui-resizable {
position: absolute !important;
}
<link rel="stylesheet" href="//code.jquery.com/ui/1.11.2/themes/smoothness/jquery-ui.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="//code.jquery.com/ui/1.11.2/jquery-ui.js"></script>
<div class="form-group">
<label>ADD two line and RESIZE THE FIRST LINE it will scroll down the line added after it. NOW add a 3rd line and resize the second line it will scroll down the 3rd line and if you resize the very first line you added it will scroll down the other lines</label>
<div id="main">
<button id="s">add line</button>
</div>
<div id="line" class="hidden">
<label class="dra"></label>
</div>
You can adjust the positioning however you want.
If your label is:
<div class="label">Lorem ipsum</div>
add this CSS:
.label {
white-space: nowrap;
}

Using JavaScript to center multiple divs in a fluid layout

I'm trying to align multiple divs in the center of a container div. I am using the modulus function to work out the padding needed from the left hand side of the page. Here is the JavaScript I am using:
JavaScript
window.addEventListener("resize", winResize, false);
var width, leftPad, space, boxWidth;
winResize();
function winResize() {
width = document.getElementById('body').offsetWidth;
boxWidth = 350 + 10 + 10;
space = width % boxWidth;
document.getElementById('a').innerHTML = width + '....' + space;
leftPad = space / 2;
document.getElementById('container').style.paddingLeft = leftPad + 'px';
document.getElementById('container').style.width -= leftPad;
};
The HTML is as follows:
<div id="container">
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
</div>
And the CSS:
#container {
width: 100%;
float: left;
}
#container .block {
width: 350px;
height: 350px;
background-color: 4e4e4e;
float: left;
margin: 10px;
}
My problem is with this code, the padding on the left pushes the container div to the right, which makes the page wider than the window. I have tried removing the padding from the width of the container (in the bottom line of the winResize function) but this doesn't seem to do anything. Is there a way I can remove this "excess div" with CSS padding/margins?
What I can perceive is that you are trying to make container look in the center of your page, js is not required to do it and prefer not use js to position static elements in your page ever.
Here is the css you should use to make it come in center and fluidic
#container {
width: 100%;
text-align:center;
}
#container .block {
width: 350px;
height: 350px;
background-color: #4e4e4e;
display:inline-block;
margin: 10px;
}
Also you can see this fiddle : http://jsfiddle.net/ghFRv/
I would like to know if there is any reason why you want to CENTER an html element?
This is a CSS job and CSS does a very good job at it.
If you want to center your DIVS you could use margin: 0 auto; on the .block.
This would center your layout and keep the elements block level as well.
Your css would look like this:
#container {
width: 100%; /*Remove the float, it's not needed. Elements align top-left standard.*/
}
#container div.block {
width: 350px; /*Makes it possible for margin to center the box*/
height: 350px;
background: #4e4e4e; /*background is the shorthand version*/
margin: 10px auto; /*10px to keep your margin, auto to center it.*/
}
This should get rid of your problem, and makes your page load faster since theres no JS plus, the layout can never be "disabled" due to JS being disabled.
Hope this helped, if it did don't forget to upvote / accept answer
&dash; Sid

Categories