jQuery CSS method update on resize? - javascript

After struggling to vertically centre a div inside the body element using the "conventional" methods, I've decided to create a small jQuery function that figures out how far from the top an element needs to be to be "centred".
It works like this:
Get container height,
Get child height,
"top" = "(container.height - child.height) / 2"
Set margin top of child to the value of "top".
For example if the body had a width and height of 1000px and this body had a div.inner child that had a width and height of 400px the margin-top of div.inner would be 300px because (1000-400) / 2 = 300.
Here is a diagram to further explain what I mean:
NOTE: X represents the margin-top of the div.inner (as I didn't have enough space for "Margin Top = ").
To my amazement this actually works!!! Here is the test code:
// set the margin top for ".vertical-centre" elements
$(".vertical-centre").each(function() {
// set the margin-top for the child
$(this).css("margin-top", function() {
// NOTE: margin = (container.height - child.height) / 2
var margin = ($(this).parent().height() - $(this).height()) / 2;
// default the margin to zero if it's a negative number
// round the margin down to the nearest whole number
// specify that the margin-top is in pixels
return Math.floor(Math.max(0, margin)) + "px";
});
});
body {
width: 100px;
height: 100px;
margin: 0;
padding: 0;
border: 1px solid black
}
div.inner {
width: 40px;
height: 40px;
background-color: blue
}
.horizontal-centre {
display: block;
margin-left: auto;
margin-right: auto
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="inner horizontal-centre vertical-centre"></div>
NOTE: I made the example above smaller so you could see it properly.
Unfortunately though, there is now another problem, when I resize the browser the margin-top of the div.inner element stays the same.
I would like for it to be responsive and update it's margin-top property to the appropriate value when the window has been resized otherwise div.inner will go out of view and the page will look a like this:

You could use https://api.jquery.com/resize/
Create a function of your code
function init_center() {..
Try calling the init_center function from the resize event of window
SNIPPET
function init_center() {
// set the margin top for ".vertical-centre" elements
$(".vertical-centre").each(function() {
// set the margin-top for the child
$(this).css("margin-top", function() {
// NOTE: margin = (container.height - child.height) / 2
var margin = ($(this).parent().height() - $(this).height()) / 2;
// default the margin to zero if it's a negative number
// round the margin down to the nearest whole number
// specify that the margin-top is in pixels
return Math.floor(Math.max(0, margin)) + "px";
});
});
}
$( window ).resize(init_center); // Handle resize of window
init_center(); // Doing it first time
body {
width: 400px;
height: 400px;
margin: 0;
padding: 0;
border: 1px solid black
}
div.inner {
width: 200px;
height: 200px;
background-color: blue
}
.horizontal-centre {
display: block;
margin-left: auto;
margin-right: auto
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="inner horizontal-centre vertical-centre"></div>

Wrap you code in a function
function align() {
$(".vertical-centre").each(function() {
// set the margin-top for the child
$(this).css("margin-top", function() {
// NOTE: margin = (container.height - child.height) / 2
var margin = ($(this).parent().height() - $(this).height()) / 2;
// default the margin to zero if it's a negative number
// round the margin down to the nearest whole number
// specify that the margin-top is in pixels
return Math.floor(Math.max(0, margin)) + "px";
});
});
}
And run it on window resize as well
align(); // first run
$(window).on('resize', align); // when window resize

Related

Change width of contenteditable div by chuncks based on text

I'm trying to change the width of a div based on the content of the div:
Lets say initially the div has a width of 100px, I want it to remain at that width until the user has filled up 90px with text.
When this arrive the width of the div should be incremented by a fixed value. if the user writes even more (190px) the div will again have its width incremented.
I tried using the clientWidth of the div like this:
get style(): string {
if (!this.el) {
return `
width: 100px;
line-height: ${DEFAULT_HEIGHT}px;
max-height: inherit;
`;
}
let divWidth = 100;
const maxWidth = window.innerWidth - SCROLLBAR_WIDTH;
while (this.el.clientWidth > divWidth * 0.9 && divWidth < maxWidth) {
const width = width + 100
if (width > maxWidth) {
break;
}
divWidth = width;
}
return `
width: ${divWidth}px;
line-height: ${DEFAULT_HEIGHT}px;
max-height: inherit;
`;
}
but it does compare the width of the div with itself and not the content of the div.
Thanks in advance,
You can relate to this answer to get the content width: https://stackoverflow.com/a/47224153/12933115
My recommendation is that you use two nested DIVs like this:
<div id="container">
<div id="content"></div>
</div>
<input id="txtBox" />
The div#container would have a fixed size, whereas the div#content wouldn't.
#container {
width: 100px;
}
#content {
max-width: fit-content;
max-width: -moz-fit-content; /* For Mozilla Firefox */
}
Now, you detect the typing instead of the width. Then, you check the width of the inner DIV within the event listener.
const input = document.getElementById("txtBox");
input.addEventListener("input", () => {
// Check the width of the inner DIV (#content) here...
// If the width of the inner width exceeds your limit, then you change the width
// of the container DIV (#container).
});
The above was a general explanation. You'll figure out how to apply this according to your needs.

Is there any way to change a div size on scroll using intersectionObserver?

I'm trying to change the size (or scale) of a div while scrolling.
This div has a .8 scale attached to it css. I'd like to reach a scale of 1 progressively while scrolling.
IntersectionObserver seems to be a good choice to work with instead of scroll event but i don't know if i can change the state of an element using it.
You can change the scale of a div using.
document.getElementById("scaledDiv").style.transform = "scale(1)";
The scroll event should do what you want it to do. You can continue to add more if statements and check how many pixels they are scrolling to change it gradually to 1 or even back to 0.8 when they scroll back up. The 50 below represents 50 pixels from the top of the page.
window.onscroll = function() {
if (document.body.scrollTop > 50 || document.documentElement.scrollTop > 50) {
// They are scrolling past a certain position
document.getElementById("scaledDiv").style.transform = "scale(1)";
} else {
// They are scrolling back
}
};
I hope this will help you:
const container = document.querySelector('.container');
const containerHeight = container.scrollHeight;
const iWillExpand = document.querySelector('.iWillExpand');
container.onscroll = function(e) {
iWillExpand.style.transform = `scale(${0.8 + 0.2 * container.scrollTop / (containerHeight - 300)})`;
};
.container {
height: 300px;
width: 100%;
overflow-y: scroll;
}
.scrollMe {
height: 1500px;
width: 100%;
}
.iWillExpand {
position: fixed;
width: 200px;
height: 200px;
top: 10px;
left: 10px;
background-color: aqua;
transform: scale(0.8);
}
<div class='container'>
<div class='scrollMe' />
<div class='iWillExpand' />
</div>

height of child related to parent width

I have grid like this and my sidebar take 4 of 12 col near to 33.3% and my sidebar is parent element
$susy: (
columns : 12,
gutters : 1/1.618033989/1.618033989/1.618033989,
math : fluid,
output : float,
gutter-position : inside,
);
#include border-box-sizing;
.sidebar {
height: 100vh;
#include span(4);
}
and I have div tag in my side bar and width of child is 100% of parent, now I want height of child be width of parent*number
I have tried some thing like this
width: 33.3333vw;
height:20.601112354vw;
but that work when we are out of grid when there is no parent element
and I have tried this
#container {
display: inline-block;
position: relative;
width: 50%;
}
#dummy {
margin-top: 75%; /* 4:3 aspect ratio */
}
#element {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background-color: silver /* show me! */
}
but there is many bugs in this method like you put 2 or more div tag in child and working with this should be full of tricks
I want some method that simply get width of parent and multiply that and make that height of child element.so when we resizing browser when width of parent get change -> height of child get change
var width = $('.child').width();
var parentWidth = $('.sidebar').width();
var ratio = parentWidth/1.618033989;
$(".child").height(ratio);
$( window ).resize(function() {
var width = $('.child').width();
var parentWidth = $('.sidebar').width();
var ratio = parentWidth/1.618033989;
$(".child").height(ratio);

Animation for the automatic height change when content is resized with javascript

I want to control the automatic height change of the container when I add something that changes the lenght of the content. Right now, if I apply a innerHTML change on the content, the height is changed accordingly. I want to apply a transition to that height change. How can I do that? ( I can also use jQuery )
Record the height before changing the content, change the content, record the height after, set the height to the former height, and animate to the latter height. When the animation has completed, set the height to be automatic again. You can do this using height and animate.
Try it on JSFiddle.
var texts = [
"This is just some sample text that's being used to demonstrate animating the height when content changes.",
"Shorter."
];
var div = $('div').click(changeContent);
function changeContent() {
var oldHeight = div.height();
texts.push(div.text());
div.text(texts.shift());
var newHeight = div.height();
div.height(oldHeight);
div.animate({height: newHeight}, 'fast', function() {
div.height('auto');
});
}
div {
width: 150px;
background: lightgray;
overflow-y: hidden;
}
<div>This is some example content.</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<div id="containter" style="overflow:hidden">
<div>
Content.....
</div>
</div>
//add something...
$('#container').animate({height:$('#container').content().outerHeight()});
or:
$('#container').animate({height:$('#container').children().first().outerHeight()});
and when adding append to the div inside the containter:
$('#container').children().first().append(somethingNew);
Based on icktoofay's answer.
I make the button disabled while changing the height and add a fading effect. This solution is useful for updating of the products filter and so on.
Also I check the box-sizing property. If it's box-sizing then I get newHeight by .outerHeigth() instead of .height() to prevent the height fluctuation when new content has the same height. You can check this situation, for example by setting the random variable to value 5. The reason is that
.height() will always return the content height, regardless of the value of the CSS box-sizing property.
CodePen
$('#button').click(function() {
var $button = $(this),
buttonOriginalText = $button.html();
$button.prop('disabled', true).html('Updating...');
$('#content').animate({
opacity: 0
}, 'fast', function() {
var newHeight,
$content = $(this),
oldHeight = $content.height();
$content.html(getRandomContent());
newHeight = ('border-box' === $content.css('box-sizing') ? $content.outerHeight() : $content.height());
$content.height(oldHeight).animate({
height: newHeight,
opacity: 1
}, 'slow', function() {
$content.height('auto');
$button.prop('disabled', false).html(buttonOriginalText);
});
});
});
function getRandomContent() {
var random = 1 + Math.round(Math.random() * 11), // 1..12
paragraph = '<p>Paragraph</p>';
return paragraph.repeat(random);
}
* {
box-sizing: border-box; /* comment out to test "content-box" */
font: 16px Helvetica, 'sans-serif';
}
.content {
counter-reset: content;
padding: 6px 18px;
}
.content p {
counter-increment: content;
}
.content p:after {
content: ' ' counter(content) '.';
}
.content-box {
border: 2px solid red;
margin-top: 24px;
max-width: 220px;
}
<button id="button" class="button">Update the content</button>
<div class="content-box">
<div id="content" class="content">Animatie the automatic height when content is resized.</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>

How to keep a floating div centered on window resize (jQuery/CSS)

Is there a way (without binding to the window.resize event) to force a floating DIV to re-center itself when the browser window is resized?
To help explain, I imagine the pseudocode would look something like:
div.left = 50% - (div.width / 2)
div.top = 50% - (div.height / 2)
UPDATE
My query having been answered below, I wanted to post the final outcome of my quest - a jQuery extension method allowing you to center any block element - hope it helps someone else too.
jQuery.fn.center = function() {
var container = $(window);
var top = -this.height() / 2;
var left = -this.width() / 2;
return this.css('position', 'absolute').css({ 'margin-left': left + 'px', 'margin-top': top + 'px', 'left': '50%', 'top': '50%' });
}
Usage:
$('#mydiv').center();
This is easy to do with CSS if you have a fixed-size div:
.keepcentered {
position: absolute;
left: 50%; /* Start with top left in the center */
top: 50%;
width: 200px; /* The fixed width... */
height: 100px; /* ...and height */
margin-left: -100px; /* Shift over half the width */
margin-top: -50px; /* Shift up half the height */
border: 1px solid black; /* Just for demo */
}
The problem, of course, is that fixed-size elements aren't ideal.
The simplest way would be with the following CSS code:
#floating-div {
width: 50%;
border: 1px solid gray;
margin: 0 auto;
}
The key line of CSS code above is the "margin: 0 auto;" which tells the browser to automatically set the left/right margins to keep the div centered on the page, even when you resize the browser window.
Try this little article about Horizontal and Vertical centering. It is a little old and has a few hacks but you should be able to work out some test code from it.

Categories