Get x y position of element relative to parent div Jquery - javascript

Given the following markup:
<div class='container'>
<div class='inner'>
<div class='target'></div>
</div>
</div>
And styles:
.container {
width: 100%;
height: 100vh;
overflow: scroll;
}
.inner {
width: 3000px;
height: 2000px;
}
.target {
height: 200px;
width: 200px;
background: red;
}
How would I go about scrolling the .container with $('.container').scrollLeft(X) and $('.container').scrollTop(X) to center .target in the middle of the viewport?
I get it to work by playing around with static values but as soon as the size of the screen changes, e.g. on mobile or tablets, then the centering is off.
I've also tried doing:
$('.container').scrollLeft($('.target').position().left);
$('.container').scrollTop($('.target').position().top);
But this doesn't seem to work, the centering is way off. I dont' know if this is because the .target is contained in a div with overflow: scroll.

I hope I understood you correctly. I've added position: relative; to the .inner element and absolute to .target element and I calculated the position in jQuery based on the elements width's and height's. I hope this is what you need:
var x = $('.inner').width() / 2 - $('.target').width() / 2
var y = $('.inner').height() / 2 - $('.target').height() / 2;
$('.container').scrollLeft(x);
$('.container').scrollTop(y);
$('.target').css({
left: x,
top: y
});
.container {
width: 100%;
height: 100vh;
overflow: scroll;
}
.inner {
width: 3000px;
height: 2000px;
position: relative;
}
.target {
height: 200px;
width: 200px;
background: red;
position: absolute;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class='container'>
<div class='inner'>
<div class='target'></div>
</div>
</div>

Related

How do you make a div only extend in one direction when the outer container size increases?

I'm trying to make a a page container with a navigation bar on the left (inside of the container). When the outer page is wider than the container, I would like just the navigation bar to extend left up to a certain size while the rest of the container's contents to remain the same and stay in the middle of the outer page.
To illustrate my idea, here are the before and after images, with black representing the outer page, blue the page container, pink the leftnav, and green the rest of the container.
Here is also the general structure of the code I am writing. The jsfiddle link includes some css for detail.
<div id="page">
<div id="container">
<div id="leftCol">
LEFT
</div>
<div id="rightCol">
RIGHT
</div>
</div>
https://jsfiddle.net/6L1zrj6e/1/
Currently, my container has a fixed width and automatic margins so as to center it. Is what I am trying to achieve even possible with the current layout? Would I need to move the leftnav div outside of the container?
Here's a pure css solution: fiddle
This is a trick I learned here: here
where you have to put the float first, then make the div respect it by creating a new block formatting context, then the div will expand to the remaining space. Throw in a couple min/max widths to conform it and a wrapper with min/max widths as well and it falls into place. The html background makes the body background not extend past the body as it normally would. Another little trick.
<div class="wrap">
<main></main>
<nav></nav>
</div>
html {
background: white;
}
body {
background: purple;
padding: 0;
margin: 0;
}
.wrap {
margin: 0 auto;
max-width: 1080px;
min-width: 920px;
}
nav {
overflow: auto; /* force a new context to respect float */
background: red;
height: 300px;
min-width: 200px;
max-width: 360px;
}
main {
float: right;
background: green;
height: 300px;
width: 720px;
}
You can try the following: Full screen example
jsFiddle
HTML:
(Took leftCol out of container)
<div id="page">
<div id="leftCol">
LEFT
</div>
<div id="container">
<div id="rightCol">
RIGHT
</div>
</div>
</div>
JS: (Update the width on page resize and on load)
$(window).on('resize', function(){
var containerWidth = 980;
var pageWidth = $(window).width();
var tempW = Math.max(0, pageWidth-containerWidth) / 2;
tempW += 200;
var w = Math.min(tempW, 360); // 360 = max width
var l = Math.max(0, tempW - w);
$('#leftCol').css({'width': w+'px', 'left': l+'px'});
}).resize();
CSS: (Removed floats, using absolute position for leftCol)
#page{
background-color: purple;
position:relative;
}
#container {
background-color: blue;
width: 980px;
height: 300px;
margin: 0 auto;
}
#leftCol {
position:absolute;
top: 0;
left: 0;
background-color: red;
height: 300px;
width: 200px;
}
#rightCol {
padding-left:200px;
background-color: green;
height: 300px;
width: auto;
}
This is what I think you're after - forgive me if I'm wrong!
EDIT: Added outer container wrapper for right margin:
Updated HTML:
<div id="page">
<div id="outercontainer">
<div id="container">
<div id="leftCol">
LEFT
</div>
<div id="rightCol">
RIGHT
</div>
</div>
</div>
</div>
And the CSS:
#page{
background-color: purple;
height: 300px;
}
#outercontainer {
margin: 0 5% 0 0;
}
#container {
background-color: blue;
height: 300px;
margin: 0 auto;
min-width: 300px;
max-width: 600px;
position: relative;
}
#leftCol {
background-color: red;
height: 300px;
margin-right: 200px;
}
#rightCol {
position: absolute;
background-color: green;
width: 200px;
top: 0;
right: 0;
bottom: 0;
}
This gives the #container a min and max width, and the margins will show beyond the max. These are set quite small to show up well in JSFiddle.
leftCol will expand to fit the available space, and it's right-margin prevents it overflowing the rightCol.
rightCol is absolutely positioned (within #container) in the leftCol's margin.
JSFiddle here: https://jsfiddle.net/xuew6og5/1/
The #outerwrapper allows a visible right margin, until the page gets to minimum width at least. If you want the margins to be balanced, change its margin to 0 5%
Update: New JS Fiddle with right margin: https://jsfiddle.net/xuew6og5/2/
Update 3: Sorry, I missed your requirement for a max-width of 360px on the leftCol. Updated the CSS above, and a fiddle here: https://jsfiddle.net/xuew6og5/4/
In order to achieve the wanted effect you need to move the leftCol outside of your container and give your rightCol a margin-left with the size of your leftCol.
Also add a min-width and max-width to your lefCol and a width using calc to adjust it's width to your goals.
Note: lefCol width is calculated like this:
100% / 2 - (Container width / 2 - leftCol min-width)
So your altered html looks like this:
<div id="page">
<div id="leftCol">
LEFT
</div>
<div id="container">
<div id="rightCol">
RIGHT
</div>
</div>
</div>
Your new CSS looks like this:
#page{
background-color: purple;
}
#container {
background-color: blue;
width: 300px;
height: 300px;
margin: 0 auto;
}
#leftCol {
float: left;
background-color: red;
height: 300px;
min-width:100px;
width:calc(100%/2 - 50px);
max-width:200px;
}
#rightCol {
margin-left:100px;
background-color: green;
height: 300px;
width: 200px;
}
Take a look at the updated example:
https://jsfiddle.net/xxyv7nwf/2/
CSS solution using CSS3 calc.
Edited. According to OP updates.
#media screen and (min-width: 1600px) {
#container{
margin:0 auto;
}
}
body {
overflow-x:hidden;
}
#page{
background-color: purple;
height:300px;
}
#container{
background-color: blue;
min-width:980px;
max-width: 1140px;
}
#leftCol {
float: left;
background-color: red;
height: 300px;
width: calc(100% - 780px);
}
#rightCol {
float: left;
background-color: green;
height: 300px;
width: 780px;
}
HTML
<div id="page">
<div id="container">
<div id="leftCol">
LEFT
</div>
<div id="rightCol">
RIGHT
</div>
</div>
</div>

How to make a relatively positioned child to get all parent's height

I have this layout
body, html {
height: 90%;
}
#content{
width: 100%;
height: 100%;
}
#sidebar {
position: relative;
width: 200px;
float: left;
height: 100%;
background-color: green;
}
#sidebar-content {
height: 120px;
background-color: blue;
}
#sidebar-footer {
position: absolute;
bottom: 0;
height: 50px;
width: 100%;
background-color: black;
}
#main {
position: relative;
overflow: hidden;
background-color: red;
}
#main-content {
height: 750px;
}
<div id="content">
<div id="sidebar">
<div id="sidebar-content">
</div>
<div id="sidebar-footer">
</div>
</div>
<div id="main">
<div id="main-content">
</div>
</div>
</div>
I need the sidebar to occupy all height available if it's height lower than the #main's. Setting the sidebar position to absolute solves this, but adding even more bugs, is there a solution for the relatively positioned child to get all the parent's height without specifying height of the parent in pixels?
As you can see in the fiddle, if #main exceeding the sidebar's width the sidebar is shorter, but it need to fill all the height.
CSS Flexbox does indeed solve your problem, and is the perfect answer if you don't have to support older browsers.
Basically, just adding display: flex to the container will sort this out for you.
Browsers support flexbox in a variety of ways, make sure you check the compiled CSS of that Pen to get all the browser pre-fixes and such.
Link to CodePen
You may be able to use a combination of css properties to achieve what you are looking for. The main reason you were running into trouble with the position:absolute was due to your float:left.
Have a glance through this and you may find some of the positioning and width declarations useful in your implementation:
body,
html {
height: 90%;
}
#content {
width: 100%;
height: 100%;
position: relative;
background: lightgray;
}
#sidebar {
position: absolute;
width: 200px;
height: 100%;
top: 0;
left: 0;
background-color: green;
z-index: 8;
}
#sidebar-content {
height: 120px;
background-color: blue;
}
#sidebar-footer {
position: absolute;
bottom: 0;
height: 50px;
width: 100%;
background-color: black;
}
#main {
overflow: hidden;
background-color: red;
height: 100%;
position: absolute;
top: 0;
left: 200px;
width: calc(100% - 200px);
height: 100%;
z-index: 10;
}
#main-content {}
<div id="content">
<div id="sidebar">
<div id="sidebar-content">
</div>
<div id="sidebar-footer">
</div>
</div>
<div id="main">
<div id="main-content">this is the main content
</div>
</div>
</div>
I guess jQuery solution will help you solve your problem :) Try this This will allow to have the #sidebar to have same height as the container. Hope this helps :) Happy coding.
jQuery:
$(document).ready(function(){
var wrapH = $('#content').outerHeight();
$('#sidebar').css("height", wrapH);
});
Edited:
JS Fiddle Link
$(document).ready(function(){
var wrapH = $('#main').outerHeight();
$('#sidebar').css("height", wrapH);
});
Just change the content to main. Hope this solves the issue. This will make the sidebar height be the same as the main height.

Responsive width on main column using JS

I have a responsive layout with 2 colums (main & sidebar). The side bar has a fixed width and the main column's width is responsive. do to the sidebar being a fixed width, I can't set the main column to 100% without the sidebar dropping down obviously. Is there any way to let javascript calculate the width of the main column depending on browser size? (taking into account the fixed width column that should be next to it)
#main {
background-color: #0F0;
float: left;
height: 400px;
width: 100%;
}
#sidebar {
background-color: #C60;
float: right;
height: 400px;
width: 300px;
}
<div id="main">
</div>
<div id="sidebar">
</div>
This is possible using CSS's calc() function.
#main {
background-color: #0F0;
float: left;
height: 400px;
width: calc(100% - 300px);
}
#sidebar {
background-color: #C60;
float: right;
height: 400px;
width: 300px;
}
body {
margin: 0;
}
<div id="main">
</div>
<div id="sidebar">
</div>
If you really want to use JavaScript you need set main's width equal to the window's width without scrollbar (document.body.clientWidth) minus sidebar's width.
Also, the function doMath() needs to be executed when the window is resized.
var main = document.getElementById('main');
var sidebar = document.getElementById('sidebar');
function doMath() {
main.style.width = document.body.clientWidth - sidebar.offsetWidth + 'px';
}
doMath();
window.onresize = doMath;
#main {
background-color: #0F0;
float: left;
height: 400px;
width: 100%;
}
#sidebar {
background-color: #C60;
float: right;
height: 400px;
width: 300px;
}
body {
margin: 0;
}
<div id="main">
</div>
<div id="sidebar">
</div>

Emulating a fixed sidebar template issues

am trying to emulate this theme:
http://themetrust.com/demos/ink/?project=the-city-of-samba
But instead make the blog post always remain centered in the right hand side (space outside of the fixed sidebar) and have the blog post be of a % width.
I currently have this set up on my site, but am using a percentage based sidebar which looks awful.
Here is a JSfiddle recreating in basic terms the theme from above:
http://jsfiddle.net/Uyv6w/4/
All i am after is to make that grey inner div always remain centered inside the red content div.
Incase JSFiddle goes down and for future ref:
HTML:
<div id="container">
<div id="sidebar"></div>
<div id="content">
<div id="inner"></div>
</div
</div>
CSS:
* {
margin: 0; padding: 0;
}
html, body {
width: 100%;
height: 100%;
background-color: #333;
}
#container {
height: 100%;
width: 100%;
}
#sidebar {
height: 100%;
width: 100px;
background-color: #9b59b6;
position: fixed;
}
#content {
width: 100%;
background-color: #f00;
}
#inner {
width: 60%;
margin-left: 150px;
background-color: #888;
height: 1000px;
}
Thanks.
There are just 2 properties to change in ordre to make this work the way you want :
#content {
/* width: 100%; */
margin-left: 100px; /* the width of you sidebar.
Since #content is a div, a block-level element
, its width will be automatically 100%
, minus the margins */
background-color: #f00;
}
#inner {
width: 60%;
/* margin-left: 150px; */
margin-left: auto;
margin-right: auto; /* having margin-left & right set to auto will center your div.
you could also use "margin: 0 auto" */
background-color: #888;
height: 1000px;
}
I have updated you JSFiddle example here : http://jsfiddle.net/Uyv6w/5/
http://jsbin.com/requv/1/edit
if you set body, html (and the container) to height 100%, it will not be able to to scroll.
the height should be more then 100%.

css overflow hidden to display images that are within defined "window" div

I'm trying to setup the css for a native javascript animation. There are going to be several images that enter a "window" which is 600px. As one image slides in or out, the only visible part will be the part of the images that is within the window. I've had several attempts at setting this up with css before I start javascript animating, which include things like overflow:hidden on the rotator div and setting it's width, however that doesn't seem to work.
#rotator {
width: 600px;
height: 320px;
background: #131313;
/*text-align: left;*/
/*display: inline-block;*/
overflow: hidden;
/*position: relative;*/
/*float: left;*/
}
.box_wrapper {
width: 450px;
/*position: absolute;*/
display: inline-block;
/*overflow: hidden;*/
}
<div id="rotator">
<div class="box_wrapper">
<h4>Header1</h4>
<img src="../img/kat_3.jpg" /><br/>
</div>
<div class="box_wrapper box_2">
<h4>Header2</h4>
<img src="../img/kat_2.jpg" /><br/>
</div>
</div>
The images either fully show up or not at all when messing with the css properties.
you need set the width or height of the images, so they can be scaled into the the divs.
<style>
#rotator {
width: 600px;
height: 320px;
background: #131313;
overflow: hidden;
}
.box_wrapper {
width: 450px;
height: 100%;
display: inline-block;
}
</style>
$('.box_wrapper').each(function() {
var $el = $(this), $img = $el.find('img'), fixedRatio = 600 / 320,
ratio = $img.width() / $img.height(),
offset = $img.offset().top - $el.offset().top;
if (ratio > fixedRatio) {
$img.width($el.width()).height('auto');
} else {
$img.height($el.height() - offset).width('auto');
}
});

Categories

Resources